zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    oracle使用expdp备份数据库
    用Setuptools构建和分发程序包
    C#5.0-原生异步编程方式
    任务并行库
    线程-线程池1
    多线程-3(同步)
    多线程-2(线程同步)
    线程---1
    高性能-GC3
    高性能-GC2
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9716794.html
Copyright © 2011-2022 走看看