uva 1633 Dyslexic Gollum

题意:

给出n和k,求出长度为n的不包含长度大于等于k的回文串的01字符串的个数。

思路:

如果一个字符串包含长度为k的回文串,那么它肯定包含长度为k-1的回文串,所以考虑第i位的时候,只要前缀中不包含长度为k的回文串,就只需要考虑这一位使其满足条件,所以就可以进行递推dp了。

设dp[i][j]为长度为i的字符串且最后k位为j时满足的串的个数,因为k较小,所以可以进行状态压缩。

但是考虑k的长度是不行的,还需要考虑k+1才行,比如k = 4,j为0010,那么转移就可以转移到00100,后四位虽然满足,但是这5位显然是个回文串,所以需要考虑多一位。

首先预处理出长度为i,状态为j时是否时回文串。

bit数组用于保存2的i-1次方,即bit[i] = 2^(i-1)。

cal用于计算当前的最后k位。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 405;
 6 const int K = 13;
 7 const int mod = 1e9 + 7;
 8 bool pal[K][1<<K];
 9 int bit[K];
10 int dp[N][(1<<K)];
11 bool check(int x,int k)
12 {
13     int b[K];
14     memset(b,0,sizeof(b));
15     int cnt = 0;
16     while (x)
17     {
18         b[cnt++] = x % 2;
19         x /= 2;
20     }
21     for (int i = 0;i < k/2;i++)
22     {
23         if (b[i] != b[k - i - 1]) return 0;
24     }
25     return 1;
26 }
27 int cal(int x,int y,int k)
28 {
29     if (x >= bit[k]) x -= bit[k];
30     return x << 1 | y;
31 }
32 int main()
33 {
34     bit[0] = 0;
35     bit[1] = 1;
36     for (int i = 2;i < K;i++) bit[i] = bit[i-1] << 1;
37     for (int i = 1;i < K;i++)
38     {
39         for (int j = 0;j < (1<<i);j++)
40         {
41             if (check(j,i)) pal[i][j] = 1;
42         }
43     }
44     int t;
45     scanf("%d",&t);
46     while (t--)
47     {
48         int n,k;
49         scanf("%d%d",&n,&k);
50         if (k == 1)
51         {
52             puts("0");
53             continue;
54         }
55         memset(dp,0,sizeof(dp));
56         dp[0][0] = 1;
57         for (int i = 1;i <= n;i++)
58         {
59             for (int j = 0;j < (1 << min(i,k));j++)
60             {
61                 if (!dp[i-1][j]) continue;
62                 for (int x = 0;x < 2;x++)
63                 {
64                     int sta = cal(j,x,k);
65                     if (i >= k && pal[k][sta]) continue;
66                     if (i >= k + 1 && (pal[k+1][j<<1|x])) continue;
67                     dp[i][sta] += dp[i-1][j];
68                     dp[i][sta] %= mod;
69                 }
70             }
71         }
72         int ans = 0;
73         for (int i = 0;i < (1<<k);i++)
74         {
75             ans += dp[n][i];
76             ans %= mod;
77         }
78         printf("%d\n",ans);
79     }
80     return 0;
81 }
82 /*
83 3 2 2 3 3 3 4
84 */

 

posted @ 2018-05-04 00:43  qrfkickit  阅读(390)  评论(0编辑  收藏  举报