这道题说连续子序列, 马上就想到滑动窗口。
注意窗口里面的元素中小于等于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; }