CF 314 E. Sereja and Squares
2018-09-28 09:19
274 查看
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。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<iostream> #include<cctype> using namespace std; typedef unsigned int ui; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } char s[100005]; ui f[100005]; int main() { int n = read(); if (n & 1) { cout << 0; return 0; } scanf("%s", s + 1); int cnt = 0; f[0] = 1; for (int i=1; i<=n; ++i) { if (s[i] == '?') for (int j=(i>>1); j&&j>=(i-n/2); --j) f[j] += f[j - 1]; else cnt ++; } ui ans = f[n / 2]; for (int i=1; i<=(n/2-cnt); ++i) ans = ans * 25; cout << ans; return 0; }
相关文章推荐
- CF_314D_Sereja and Periods
- CF 314B: Sereja and Periods
- CF 314A(Sereja and Contest-这题题目索性没看懂,E文是硬伤)
- CodeForces 314 B.Sereja and Periods 思维+简单dp【转】
- CF 315B - Sereja and Array(树状数组)
- CF 426C--Sereja and Swaps
- CodeForces 314B - Sereja and Periods 很有思维的DP
- CF380A Sereja and Prefixes
- Codeforces 314 E. Sereja and Squares
- CF-Sereja and Algorithm
- cf B. Sereja and Suffixes
- (CF)B. Sereja and Contests
- cf Sereja and Array
- cf C. Sereja and Algorithm
- cf-381A-Sereja and Dima
- CF 315B(Sereja and Array-峰顶距离统计)
- CodeForces 314 B.Sereja and Periods(dp)
- cf-Round #215 (Div. 1) -B - Sereja ans Anagrams
- B. Sereja and Suffixes(cf)
- CF 315A(Sereja and Bottles-开易拉罐)