bzoj 1856: [Scoi2010]字符串

1856: [Scoi2010]字符串

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 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 }
View Code

 

posted @ 2019-09-17 23:41  zjxxcn  阅读(217)  评论(0编辑  收藏  举报