UVA 11536 Smallest Sub-Array
题意:
x[i]=(x[i-3]+x[i-2]+x[i-1])%m+1,求一段x的最短的连续子序列,使得这个子序列包含正整数【1,k】。
分析:
扫描一遍即可,用一个队列记录下【1,k】区间内的数的位置,再用一个变量count维护【1,k】内不重复数的个数。当count等于k时说明当前序列已经满足了要求,而队列头的数的位置就是起始位置。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<utility>
#include<set>
#include<queue>
using namespace std;
typedef pair<int,int>pii;
const int INF = 0x3f3f3f3f;
const int MAXN = 1000010;
int n,m,k;
int v[MAXN];
int cnt[MAXN];
int main()
{
int t,cas=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
v[1] = 1;
v[2] = 2;
v[3] = 3;
int i,j;
for(i=4;i<=n;++i)
v[i]=(v[i-1]+v[i-2]+v[i-3])%m+1;
memset(cnt, 0, sizeof(cnt));
int minx=INF;
int count=0;
queue<int>q;
for(i=1;i<=n;++i)
{
if(v[i]>=1&&v[i]<=k)
{
q.push(i);
if(cnt[v[i]]++== 0)
{
++count;
}
while(count==k)
{
int tmp=i-q.front()+1;
minx=min(tmp,minx);
int val=v[q.front()];
if(--cnt[val]==0)
{
--count;
}
q.pop();
}
}
}
printf("Case %d: ",cas++);
if(minx == INF)
printf("sequence nai\n");
else
printf("%d\n", minx);
}
return 0;
}