zoukankan      html  css  js  c++  java
  • Codeforces 379D

    原题地址:http://codeforces.com/contest/379/problem/D

    题目大意:给出一种生成字符串的方法 s[k] = s[k - 2] + s[k - 1],其中加法意为将左右两个字符串直接相连,要求构造两个长度分别为n、m的字串s[1]、s[2],使得按照这种方法得出的s[k]中恰好含有 x 个 “AC”(意思大家都懂的……)如果无解,输出“Happy new year!”

    数据范围:3 ≤ k ≤ 50; 0 ≤ x ≤ 109; 1 ≤ n, m ≤ 100

    题目分析:

    这道题算法很明确。

    先将问题反过来思考:假设给定两个串s[1]、s[2],用题目中的方法生成s[k],求出s[k]含有几个“AC”,显然可以用动态规划解决

    定义f[k]表示第k个串中含有“AC”的个数,Suf[k]为第 k 个串的结尾字母,Pre[k]为第k个串的开头字母,三个数组的1、2两位都是已知的

    显然可以得到动态规划方程 f[k] = f[k - 2] + f[k - 1] + (Suf[k - 2] == 'A') && (Pre[k - 1] == 'C');   Suf[k] = Suf[k - 1];   Pre[k] = Pre[k - 2]

    然后搞一搞就得到答案了。那么我们回归这道题,发现可以通过枚举f[1]、f[2]、Suf[1]、Suf[2]、Pre[1]、Pre[2]来DP计算所有可能的f[k],如果找到一组f[1]、f[2]、Suf[1]、Suf[2]、Pre[1]、Pre[2]使得f[k] == x,就按照它们构造两个字符串输出就好了

    复杂度分析:每次枚举Pre[1]等等都是三种情况(是A、是C、不是A也不是C),一共枚举4轮,枚举f[1]时不可能超过二分之n,枚举f[2]时也同理,所以枚举的总复杂度是O(3 * 3 * (m / 2) * 3 * 3 * (n / 2))大约为202500,每次DP都是线性的所以复杂度是O(k)所以总复杂度可以约归为O(nmk)大概在10^7左右勉强不会超时。

    剩下的就是细节了,这道题一大堆特殊情况需要判断(比如n , m <= 2啦什么的),详见代码~

     1 //date 20140120
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 inline int min(int a, int b){return a < b ? a : b;}
     6 inline int max(int a, int b){return a > b ? a : b;}
     7 
     8 int k, n, m;
     9 long long x;
    10 long long f[100];
    11 int suf[100], pre[100];
    12 
    13 void dp(int w)
    14 {
    15     if(w <= 2)return;
    16     if(f[w - 1] == -1)dp(w - 1);
    17     if(f[w - 2] == -1)dp(w - 2);
    18     f[w] = f[w - 1] + f[w - 2] + ((suf[w - 2] == 1) && (pre[w - 1] == 3));
    19     suf[w] = suf[w - 1]; pre[w] = pre[w - 2];
    20 }
    21 
    22 inline void output(int S1, int S2, int P1, int P2, int i, int j)
    23 {
    24 //    printf("%d %d %d %d %d %d
    ", S1, P1, i, S2, P2, j);
    25     char ans1[120], ans2[120];
    26     memset(ans1, 0, sizeof ans1);
    27     memset(ans2, 0, sizeof ans2);
    28     ans1[1] = P1 + 'A' - 1;
    29     ans2[1] = P2 + 'A' - 1;
    30     ans1[n] = S1 + 'A' - 1;
    31     ans2[m] = S2 + 'A' - 1;
    32 //    printf("%s
    %s
    ", ans1 + 1, ans2 + 1);
    33     
    34     int a1 = 110, a2 = 110;
    35     if(i > 0 && ans1[1] == 'A')
    36     {
    37         ans1[2] = 'C';a1 = 3;
    38         for(int q = 1; q < i; ++q){ans1[q * 2 + 1] = 'A'; ans1[q * 2 + 2] = 'C'; a1 = q * 2 + 3;}
    39         for(int q = a1; q < n; ++q)ans1[q] = 'B';
    40     }
    41     else
    42     {
    43         a1 = 2;
    44         for(int q = 1; q <= i; ++q){ans1[q * 2] = 'A'; ans1[q * 2 + 1] = 'C'; a1 = q * 2 + 2;}
    45         for(int q = a1; q < n; ++q)ans1[q] = 'B';
    46     }
    47     if(j > 0 && ans2[1] == 'A')
    48     {
    49         ans2[2] = 'C'; a2 = 3;
    50         for(int q = 1; q < j; ++q){ans2[q * 2 + 1] = 'A'; ans2[q * 2 + 2] = 'C'; a2 = q * 2 + 3;}
    51         for(int q = a2; q < m; ++q)ans2[q] = 'B';
    52     }
    53     else
    54     {
    55         a2 = 2;
    56         for(int q = 1; q <= j; ++q){ans2[q * 2] = 'A'; ans2[q * 2 + 1] = 'C'; a2 = q * 2 + 2;}
    57         for(int q = a2; q < m; ++q)ans2[q] = 'B';
    58     }
    59     printf("%s
    %s
    ", ans1 + 1, ans2 + 1);
    60 }
    61 
    62 int main()
    63 {
    64 //    freopen("d.in", "r", stdin);
    65     
    66     scanf("%d%I64d%d%d", &k, &x, &n, &m);
    67     
    68     for(int P1 = 1; P1 <= 3; ++P1)
    69         for(int S1 = 1; S1 <= 3; ++S1)
    70             for(int P2 = 1; P2 <= 3; ++P2)
    71                 for(int S2 = 1; S2 <= 3; ++S2)
    72                 {
    73                     if(n == 1 && S1 != P1)continue;
    74                     if(m == 1 && S2 != P2)continue;
    75                     int uLim1 = 0, uLim2 = 0, dLim1 = 0, dLim2 = 0;
    76                     uLim1 = max(n / 2 - 1, 0); if((n >= 3) && ((S1 == 3 && P1 == 1) || ((n & 1) && (S1 == 3 || P1 == 1))))++uLim1; 
    77                     uLim2 = max(m / 2 - 1, 0); if((m >= 3) && ((S2 == 3 && P2 == 1) || ((m & 1) && (S2 == 3 || P2 == 1))))++uLim2;
    78                     if(n == 2 && S1 == 3 && P1 == 1)dLim1 = uLim1 = 1;
    79                     if(m == 2 && S2 == 3 && P2 == 1)dLim2 = uLim2 = 1;
    80 //                    printf("%d %d %d %d
    ", dLim1, uLim1, dLim2, uLim2);
    81                     for(int i = dLim1; i <= uLim1; ++i)
    82                         for(int j = dLim2; j <= uLim2; ++j)
    83                         {
    84                             memset(suf, 0, sizeof suf);
    85                             memset(pre, 0, sizeof pre);
    86                             suf[1] = S1; suf[2] = S2;
    87                             pre[1] = P1; pre[2] = P2;
    88                             memset(f, 0xFF, sizeof f);
    89                             f[1] = i; f[2] = j;
    90                             dp(k);
    91 //                            printf("%d %d %d %d %d %d %d
    ", P1, S1, P2, S2, i, j, f[k]);
    92                             if(f[k] == x){output(S1, S2, P1, P2, i, j); return 0;}
    93                         }
    94                 }
    95     
    96     printf("Happy new year!
    ");
    97     return 0;
    98 }

    小注:希望通过这道题能给我和大家带来更多的新年AC~

  • 相关阅读:
    define和typedef
    keil5配置stm32库函数开发
    SPI、CAN、I2C
    flash,sram
    关于网络地址
    关于定时器、波特率、TH和TL值的计算
    关于串口工作方式
    ad各层
    AD快捷键
    OAuth2.0 微博登陆网站功能的实现(一)获取用户授权及令牌 Access Token
  • 原文地址:https://www.cnblogs.com/w007878/p/3527620.html
Copyright © 2011-2022 走看看