合法括号匹配[简单的序列,合法括号匹配]
作者:互联网
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
标签:匹配,删除,等效,ll,末位,合法,括号 来源: https://www.cnblogs.com/znsbc-13/p/11677698.html