大体题意:
给你n,m,k
从而会算出一个n个元素的集合,求出一个子集合的长度,其中子集合 存在X 满足X <= k;
思路:
建立一个vis数组,表示每个数出现的次数,然后一个一个数的遍历,只有满足当前数符合访问次数为1 并且大小小于等于k,则cnt++
然后建立一个pos表示左端的最优解的位置 寻找方法很简单 当pos位置的数 vis 大于1 或者 大小大于k 都不是最优的都应该++pos
最后当cnt == k时更新答案即可!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000000 + 10;
const int INF = 1e9;
int a[maxn];
int vis[maxn];
int n,m,k;
void init(){
a[1] = 1;
a[2] = 2;
a[3] = 3;
for (int i = 4; i <= n; ++i)a[i] = (a[i-1]+a[i-2]+a[i-3])%m+1;
}
int main(){
int T,cnt=0;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
init();
memset(vis,0,sizeof vis);
int cnt2 = 0,pos=1;
int ans = INF;
for (int i = 1; i <= n; ++i){
int x = a[i];
vis[x]++;
if (vis[x] == 1 && x <= k)++cnt2;
while(vis[a[pos]] > 1 || a[pos] > k)vis[a[pos]]--,++pos;
if (cnt2 == k)ans = min(ans,i-pos+1);
}
printf("Case %d: ",++cnt);
if (ans < INF)printf("%d\n",ans);
else printf("sequence nai\n");
}
return 0;
}