题目描述
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
输入描述:
输入数据是一行,包括2个数字n和m
输出描述:
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
示例1
输入
复制2 2
2 2
输出
复制2
2
备注:
对于30%的数据,保证 1≤m≤n≤1e3 对于100%的数据,保证 1≤m≤n≤1e6
思路:
首先普及一下卡特兰数:
给出一个n*n的正方形棋盘,求从左下角到右上角的不经过对角线的所有走法刚好是F[n],即C(2n, n)-C(2n, n-1)
然而对于这一题,可以想想象成,从(0,0)走到(n+m,n)不向下走,1代表向上,0代表向下,根据卡特兰数,可以得出最后的方案数是C(n+m,m)-C(n+m,m-1)
AC代码:
#include<bits/stdc++.h>
#define lmw ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
#define int long long
const int mod=20100403;
const int N=2e6+10;
int inf[N],f[N];
int n,m;
int ksm(int x,int y){
int res=1;
while(y){
if(y&1){
res=res*x%mod;
}
y/=2;
x=x*x%mod;
}
return res%mod;
}
int C(int x ,int y){
return f[x]*inf[y]%mod*inf[x-y]%mod;
}
inline void init(){
f[0]=1;
for(int i=1;i<=n+m;i++){
f[i]=f[i-1]*i%mod;
}
inf[n+m]=ksm(f[n+m],mod-2);
for(int i=n+m-1;i>=0;i--){
inf[i]=inf[i+1]*(i+1)%mod;
}
}
signed main(){
lmw;
// int n,m;
cin>>n>>m;
init();
if(n<m) {
cout<<"0\n";
}
else {
cout<<(C(n+m,m)-C(n+m,m-1)+mod)%mod<<"\n";
}
}