【题目链接】
http://codeforces.com/problemset/problem/629/C
【解题报告】
比赛的时候跑去做D了,这道题只是简单看了看,赛后补题把它补掉。这个题目只要想通了还是很水的。
题意很简单,给你一个长度为m的串S,让你求不同的串P和Q的方案数使长度为n的串P+S+Q为一个合法括号序列。
合法的括号序列要满足:
1.左括号和右括号数量相同
2.该串的任意一个前缀满足左括号数>=右括号数。
那么我们设dp[i][j]表示长度为i的串,(比)多j个的方案数
递推式可以列写为:dp[i]j[]=dp[i-1][j-1]+dp[i-1][j+1]
之后我们预处理出s中(比)多的个数,枚举左边(比)多的个数即可。
【解题报告】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=2e9;
const int maxn=2e5;
const int mod=1e9+7;
LL dp[2010][2010]={0};
void init( int k )
{
dp[0][0]=1;
for( int i=1;i<=k;i++ )
{
dp[i][0]=dp[i-1][1];
for( int j=1;j<=i;j++ )
{
dp[i][j]=(dp[i-1][j-1]+dp[i-1][j+1])%mod;
}
}
}
int main()
{
int n,m; cin>>n>>m;
char s[maxn]; cin>>s;
init( n-m );
int pre=-INF,suf,sum=0;
for( int i=0;i<m;i++ ){
if( s[i]==')' )sum++;
else sum--;
pre=max( pre,sum );
}
sum=0;
for( int i=m-1;i>=0;i-- ) {
if( s[i]=='(' )sum++;
else sum--;
}
suf=sum;
LL ans=0;
for( int i=0;i<=n-m;i++ )
for( int j=0;j<=n-m;j++)
{
int k=j+sum;
if( j>=pre && k>=suf && k<=n-m )
{
ans+=dp[i][j]*dp[n-m-i][k]%mod;
ans%=mod;
}
}
cout<<ans<<endl;
return 0;
}