[SCOI2010]生成字符串

XiaoX早就切了Orz

这道题是个组合数学题。

里面用到了卡特兰数的思想。

我们可以把这个操作放到坐标系上,一开始有个点在(0,0),然后把1看作(+1,+1),0看做(+1,-1)

然后我们就可以把问题视作从(0,0)出发,到(n+m,n-m),不经过y=-1的方案数。

经过y=-1的就可以对称一下,看作从(0,-2)开始,到(n+m,n-m)的方案数即可,由于要走n+m步,有n-m+1个1,m-1个0,所以最后答案是 C(n+m,m)-C(n+m,m-1)。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int mod=20100403;
const int N=2000005;
long long n,m,fac[N],inv[N];
long long ksm(long long d,long long z) {
    long long res=1;
    while(z) {
        if(z&1) res=1ll*res*d%mod;
        d=1ll*d*d%mod;
        z>>=1;
    }
    return res;
}
int main() {
    cin>>n>>m;
    fac[0]=1;
    for(int i=1;i<=n+m;i++) fac[i]=1ll*fac[i-1]*i%mod;
    inv[n+m]=ksm(fac[n+m],mod-2);
    for(int i=n+m-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    inv[0]=1;
    cout<<1ll*fac[n+m]*(1ll*inv[n]*inv[m]%mod-1ll*inv[n+1]*inv[m-1]%mod+mod)%mod;
    return 0;
}
生成字符串

 

posted @ 2018-10-16 09:51  SWHsz  阅读(142)  评论(0编辑  收藏  举报