l类似卡特兰数的推理。当然要看题解啦!
可以考虑把1的个数与0的个数的和看成x坐标,1的个数与0的个数的差看成y坐标
向右上走(x坐标加1,y坐标加1)就表示这个字符选择1。
向右下走(x坐标加1,y坐标减1)就表示这个字符选择0。
这样子,如果不考虑限制条件,就表示从(0,0)走n+m步到达(n+m,n−m),这相当于从n+m步中选出m步向右下走,也就是C(n+m,m)。
考虑限制条件,任意前缀中11的个数不少于0的个数,也就是这条路径不能经过直线y=-1。可以通过对称性发现,从(0,0)走到直线y=-1上的一点,相当于从(0,-2)走到该点。也就是说,路径经过直线y=-1的方案数就是从(0,-2)走n+m步到达(n+m,n-m),这个方案数可以用组合数表示为C(n+m,m-1)。
参考代码:
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e6+9,p=20100403;
ll n,m,f[N],inv[N] ;
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*a%p;
a=a*a%p;
b/=2;
}
return ans;
}
ll c(ll n,ll m){
ll ans=qpow(f[n-m],p-2)*qpow(f[m],p-2)%p;
return ans=f[n]*ans%p;
}
int main() {
cin>>n>>m;
f[0]=1,f[1]=1;
for(int i=2;i<=n+m;i++)
f[i]=i*f[i-1]%p;
ll ans=(c(n+m,m)-c(n+m,m-1))%p;
ans=(ans+p)%p;
cout<<ans<<endl;
return 0;
}