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

题意:

原本有一个合法的括号序列

擦去了所有的右括号和部分左括号

问有多少种填括号的方式使他仍然是合法的括号序列

括号有25种,序列长度<=1e5

传统的做法:

令dp[i][j]表示当前到第i个字符,现在还有j个左括号
若第i+1个字符是左括号,则能转移到dp[i+1][j+1]
若第i+1个字符是问号,则能转移到dp[i+1][j-1]与dp[i+1][j+1]
时间复杂度为O(n^2)
 
换种思路
再看这道题,他与传统的括号序列的不同之处是他擦去了所有的右括号
令dp[k][i]表示 假设括号只有一种,前k个里面,填了i个右括号的方案数
如果第i个是问号
若当前可以填左括号 dp[k][i]+=dp[k-1][i]
若当前可以填右括号 dp[k][i]+=dp[k-1][i-1]
dp[n][n/2]就是如果只有一种括号,使序列合法的方案数
现在有25种括号,假设序列中已有q个左括号
那么最终答案=25^(n/2-q) * dp[n][n/2]
 
这个感觉上去也是n^2的
首先把第一维压去,解决空间问题
考虑j的枚举范围
前i个里面,至多有i/2 [下取整] 个右括号
至多可以填m个左括号,所以至少有i-n/2个右括号
平摊复杂度我就不知道了
 
对2^32取模相当于unsigned int 自然溢出
 
然后就过了,跑的还很快
#include<cstdio>

using namespace std;

#define N 100002

char s[N];

unsigned int f[N<<];

int main()
{
int n;
scanf("%d",&n);
if(n&)
{
putchar('');
return ;
}
scanf("%s",s+);
int m=n>>,q=;
f[]=;
for(int i=;i<=n;++i)
if(s[i]=='?')
for(int j=i>>;j && j>=i-m;--j) f[j]+=f[j-];
else q++;
unsigned int ans=f[m];
for(int i=;i<=m-q;++i) ans*=;
printf("%u",ans);
}

最新文章

  1. [LeetCode] Word Search II 词语搜索之二
  2. 最小生成树的Kruskal算法实现
  3. PYTHON学习之路_PYTHON基础(1)
  4. 简单PHP会话(session)说明
  5. Jump Game 的三种思路 - leetcode 55. Jump Game
  6. JS rem 设置
  7. php大力力 [018节]如何联系大力力
  8. 解决RPM包相互依赖的有效方法
  9. 关于error: cannot connect to daemon的解决办法
  10. thinkphp引入类的使用
  11. 【HDOJ】4278 Faulty Odomete
  12. URI和URL
  13. HDU 2215 Maple trees
  14. Java中int类型和tyte[]之间转换及byte[]合并
  15. IIS7.5下的httpModules设置
  16. spring-session实现分布式集群session的共享
  17. java时间格式转化(毫秒 to 00:00)
  18. webAPP如何实现移动端拍照上传(Vue组件示例)?
  19. 配置 FATFS 支持长文件名
  20. Qt 布局管理

热门文章

  1. stl源码剖析 详细学习笔记deque(1)
  2. Visual studio 2017中 Javascript对于Xrm对象模型没有智能提示的解决办法
  3. 三丰云使用记录--部署iis服务器
  4. kafka学习总结之kafka核心
  5. &quot;软件&quot;和&quot;软件工程&quot;一词最早被谁提出?
  6. Beta版本冲刺(一)
  7. Spring源码解析二:IOC容器初始化过程详解
  8. 组件 -- Badge
  9. 获取select的 text
  10. linux虚拟机安装中出现的问题