题目大意:按照题目中的要求构造出一个序列,找出最短的子序列,包含1~k。
解题思路:先根据题目的方法构造出序列,然后用Towpointer的方法,用v[i]来记录当前[l, r]中有几个i;当r移动时,出现v[i] == 1时, c++(用来记录有几个1~k的数字);当c == k 时,就要移动l,当出现v[i] == 0时,c--。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int N = 1000005; 8 9 int n, m, k, v[N], g[N]; 10 11 void init() 12 { 13 memset(g, 0, sizeof(g)); 14 memset(v, 0, sizeof(v)); 15 16 cin >> n >> m >> k; 17 g[1] = 1, g[2] = 2, g[3] = 3; 18 for (int i =4; i <= n; i++) 19 g[i] = (g[i-1] + g[i-2] + g[i-3]) %m + 1; 20 } 21 22 bool solve() 23 { 24 int l =1, r = 1, c = 0; 25 int ans = n + 1; 26 while (r <= n) 27 { 28 int t = g[r++]; 29 v[t]++; 30 if(t <= k && v[t] == 1) c++; 31 32 while (l < r && c == k) 33 { 34 ans = min(ans, r - l); 35 t = g[l++]; 36 v[t]--; 37 if(t <= k && v[t] == 0) c--; 38 } 39 } 40 if(ans <= n) 41 { 42 printf("%d ", ans); 43 return false; 44 } 45 return true; 46 } 47 48 int main() 49 { 50 int cas; 51 cin >> cas; 52 for (int i = 1; i <= cas; i++) 53 { 54 init(); 55 printf("Case %d: ", i); 56 57 if(solve()) printf("sequence nai "); 58 } 59 return 0; 60 }
感觉代码好没有随和感,-:D
似乎不能,那其他的方法呢?