bzoj 1856: [Scoi2010]字符串
1856: [Scoi2010]字符串
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 2284 Solved: 1305
[Submit][Status][Discuss]
Description
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
Input
输入数据是一行,包括2个数字n和m
Output
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
Sample Input
2 2
Sample Output
2
HINT
【数据范围】
对于30%的数据,保证1<=m<=n<=1000
对于100%的数据,保证1<=m<=n<=1000000
这个题目就是考察你对卡特兰数的证明的理解,卡特兰数的拓展,用折线法证明。
答案就是C(n+m,n)-c(n+m,n+1);
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=1000000+10; 4 int const mod=20100403; 5 int inv[N<<1],n,m,pw[N<<1]; 6 int ksm(int x,int y){ 7 int ret=1; 8 while (y){ 9 if(y&1) ret=1LL*ret*x%mod; 10 x=1LL*x*x%mod; 11 y>>=1; 12 } 13 return ret; 14 } 15 int calc(int x,int y){ 16 return 1LL*pw[x]*inv[y]%mod *inv[x-y] % mod; 17 } 18 int main(){ 19 scanf("%d%d",&n,&m); 20 pw[0]=1; 21 for(int i=1;i<=n+m;i++) 22 pw[i]=1LL*pw[i-1]*i%mod; 23 inv[n+m]=ksm(pw[n+m],mod-2); 24 for(int i=n+m-1;i>=0;i--) 25 inv[i]=1LL*inv[i+1]*(i+1)%mod; 26 printf("%d\n",(calc(n+m,n)-calc(n+m,n+1)+mod)%mod); 27 return 0; 28 }