• CF 314 E. Sereja and Squares


    E. Sereja and Squares

    http://codeforces.com/contest/314/problem/E

    题意:

      给你一个擦去了部分左括号和全部右括号的括号序列,括号有25种,用除x之外的小写字母a~z表示。在擦去的地方填入一括号,求有多少种合法的括号序列。答案对4294967296取模。

    分析:

      首先dp的时候如果前面的一个左括号确定了,右边也就确定了(和它一样就行了)。左边不确定的时候'?',假设随便填入一个,最后乘以25就行了。所以状态只与左括号的个数有关。所以可以dp[i][j]表示到第i个位置,有j个左括号。考虑新加入的一个会消去左括号还是加入左括号就行了。复杂度n^2。

      优化:因为状态与左括号的个数有关,那么同样可以记录右括号的个数。考虑新加入一个消去了还是增加了。因为前i个中最多i/2个(如果记录左括号的话, 前i个便不满足这个性质,它可以有很多个,后面再很多右括号)。所以转移到i/2。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 using namespace std;
     8 typedef unsigned int ui;
     9 
    10 inline int read() {
    11     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    12     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    13 }
    14 
    15 char s[100005];
    16 ui f[100005];
    17 
    18 int main() {
    19     int n = read();
    20     if (n & 1) {
    21         cout << 0; return 0;
    22     }
    23     scanf("%s", s + 1);
    24     int cnt = 0;
    25     f[0] = 1;
    26     for (int i=1; i<=n; ++i) {
    27         if (s[i] == '?') 
    28             for (int j=(i>>1); j&&j>=(i-n/2); --j) f[j] += f[j - 1]; 
    29         else cnt ++;
    30     }
    31     ui ans = f[n / 2];
    32     for (int i=1; i<=(n/2-cnt); ++i) ans = ans * 25;
    33     cout << ans;
    34     return 0;
    35 }
  • 相关阅读:
    2020软件工程作业——团队03
    2020软件工程作业 ——团队02
    2020软件工程作业05
    2020软件工程作业04
    2020软件工程作业03
    2020软件工程作业02
    2020软件工程作业01
    微服务:基本介绍
    excel模板解析前后设计变化,以及我对此的看法和感受
    纸上得来终觉浅,绝知此事要躬行——Spring boot任务调度
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9716794.html
Copyright © 2020-2023  润新知