合法括号匹配[简单的序列,合法括号匹配]
归档于 2019-10-15 14:57
dp
简单的序列
题解
A过一遍,再做时却错了
真是具有讽刺意味
合法括号匹配
题意
每次可以在末尾加(,),或删除最末位,(长度为0时也可进行删除操作)
问最后合法方案数(长度任意)
题解
设$g[i][j]$表示进行i次操作,最终长度为j方案数
最终答案就是$\sum\limits_{i=0}^{i<=n}g[n][i]*catalan()$
模数可能不是质数$n^2$推一下catalan
然而$g$我推挂了
因为我们要求的是长度为j方案,直接的想法是将(,)等效,
$g[i][j]=g[i-1][j-1]+g[i-1][j+1]$
但实际上(,)在删除时是不等效的$[添加时仍是等效的!]$
((删除最末位,()删除最末位最终得到都是(
但这么算就算少了,
$g[i][j]=g[i-1][j-1]+g[i-1][j+1]*2$
这才是这个题要点
代码


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 5101
ll f[A][A],g[A][A];
ll n,mod;
int main(){
// freopen("da.in","r",stdin);
// freopen("ans.bf","w",stdout);
scanf("%lld%lld",&n,&mod);
f[0][0]=1;
for(ll i=1;i<=n;i++)
for(ll j=0;j<=i;j++){
if(j!=0)
f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%mod;
else
f[i][j]=f[i-1][j+1];
}
g[0][0]=1;
for(ll i=1;i<=n;i++)
for(ll j=0;j<=i;j++){
if(j==0)//j==0
g[i][j]=(g[i-1][j]+g[i-1][j+1]*2)%mod;
else
g[i][j]=(g[i-1][j-1]+g[i-1][j+1]*2)%mod;
}
ll ans=0;
for(ll i=0;i<=n;i++){
// printf("f[%lld][0]=%lld g[%lld][%lld]=%lld\n",i,f[i][0],n,i,g[n][i]);
ans=(ans+f[i][0]*g[n][i])%mod;
}
printf("%lld\n",ans);
}
View Code