uva 11536

题目大意:按照题目中的要求构造出一个序列,找出最短的子序列,包含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

能不能像这样用set来求解呢? 

似乎不能,那其他的方法呢?

原文地址:https://www.cnblogs.com/aze-003/p/5117529.html