1. 程式人生 > >BZOJ1856: [Scoi2010]字符串

BZOJ1856: [Scoi2010]字符串

algo 程序 ini esc data con cst a* algorithm

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

蒟蒻表示只會nk的DP,承擔不起 根據題解考慮轉化模型,變為從(0,0)走到(n+m,n-m),1表示斜向上走比如(0,0)走到(1,0),0則相反 那麽總數為C(n+m,m),再考慮錯誤情況 那就是走到過-1的這些情況,那麽對-1取對稱,其實就是跑了y軸中-2往上的情況 走到(n+m,n-m)需要向上走n-m+2次,一共要走n+m次。設向上向下各走x,y, 那麽x+y=n+m,x-y=n-m+2得到x=n+1,y=m-1,所以不合法的方案為C(n+m,m-1) 實力太弱實在無力
代碼如下:
//MT_LI
#include<cmath>
#include
<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll; ll mod=20100403ll; int n,m; ll pow_mod(ll a,ll b) { ll ans=1ll; while(b) { if(b&1)ans=ans*a%mod; b/=2;a=a*a%mod; } return
ans; } ll fac[2100000]; void init() { fac[1]=1ll; for(ll i=2;i<=2000000;i++) fac[i]=fac[i-1]*i%mod; } int main() { init(); scanf("%d%d",&n,&m); printf("%lld\n",(fac[n+m]*pow_mod(fac[n],mod-2)%mod*pow_mod(fac[m],mod-2)%mod-fac[n+m]*pow_mod(fac[m-1],mod-2)%mod*pow_mod(fac[n+1],mod-2)%mod+mod)%mod); return 0; }

BZOJ1856: [Scoi2010]字符串