zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    79     }
    80     return 0;
    81 }
    82 /*
    83 3 2 2 3 3 3 4
    84 */
  • 相关阅读:
    易普优高级计划排程Light版助力中小企业实现精益化计划
    06易普优APS行业方案:包装印刷行业高级计划排程
    APS高级计划排程系统应该支持的企业应用场景
    易普优APS应用案例:线束行业生产计划排产
    某PCBA企业应用易普优APS实现高级计划排程案例
    APS高级计划排程系统应该支持的企业应用场景
    oracle 字符串分割
    速度极快的导出excel
    dev winform导出功能
    sql with as union all
  • 原文地址:https://www.cnblogs.com/kickit/p/8988570.html
Copyright © 2011-2022 走看看