HDU 6084 寻找母串(卡特兰数)
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6084
【题目大意】
对于一个串S,当它同时满足如下条件时,它就是一个01偏串:
1.只由0和1两种符组成;
2.在S的每一个前缀中,0的个数不超过1的个数;
3.S中0的个数和1的个数相等。
现在给定01偏串S,请计算一下S在所有长度为n的01偏串中作为子串出现的次数的总和。
由于结果比较大,结果对1e9+7取余后输出。
【题解】
我们发现01偏串实际上等价于合法括号序列,
在合法括号序列中取出一个合法括号序列之后剩下的一定也是一个合法括号序列
所以我们计算n-lenS的合法括号序列数,乘上S在n中的位置种类即可,
计算卡特兰数时候因为模比较大,我们采用分段打表。
注意n-s<0||(n-s)%2==1条件的特判。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const LL MOD=1000000007,blk=500000; const LL lst[2001]={……}; int T,n,s; char ss[1000010]; LL Fact(LL x){ if(x<0)return 0; LL res=lst[x/blk]; for(LL i=(x/blk)*blk+1;i<=x;i++)res=(res*i)%MOD; return res; } LL power(LL a,LL b){ if(b==0)return 1; if(b&1)return(power(a,b-1)*a)%MOD; LL t=power(a,b/2);return (t*t)%MOD; } LL C(LL a,LL b){ if(a<0||b<0||a<b)return 0; return(Fact(a)*power(Fact(a-b),MOD-2)%MOD*power(Fact(b),MOD-2))%MOD; } LL Calc(int x){return (C(2*x,x)-C(2*x,x-1)+MOD)%MOD;} int main(){ scanf("%d",&T); while(T--){ scanf("%d %s",&n,ss); s=strlen(ss); if(n-s<0||(n-s)%2==1)puts("0"); else printf("%d\n",Calc((n-s)/2)*(n-s+1)%MOD); }return 0; }
愿你出走半生,归来仍是少年