这道题说连续子序列, 马上就想到滑动窗口。
注意窗口里面的元素中小于等于k的才是有效元素。记录窗口里面有效元素的个数, 满足了之后开始
缩短窗口, 如果左端点不是有效元素或者即使窗口中存在这个元素的个数大于1, 即使删去还是满足
窗口内有1到k这些元素的时候, 左端点就删去。就这样扫一遍答案就出来了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 1123456;
int a[MAXN], vis[MAXN], n, m, k;int main()
{int T, kase = 0;scanf("%d", &T);while(T--){memset(vis, 0, sizeof(vis));scanf("%d%d%d", &n, &m, &k);a[0] = 1; a[1] = 2; a[2] = 3;REP(i, 3, n) a[i] = (a[i-1] + a[i-2] + a[i-3]) % m + 1;int num = 0, ans = 2e9, l = 0;REP(r, 0, n){int cur = a[r];vis[cur]++;if(cur <= k && vis[cur] == 1) num++;if(num >= k){while(a[l] > k || vis[a[l]] > 1) vis[a[l]]--, l++;ans = min(ans, r - l + 1);}}if(ans == 2e9) printf("Case %d: sequence nai\n", ++kase);else printf("Case %d: %d\n", ++kase, ans);}return 0;
}