先mark一下別人博客:
卡特蘭數的推導(用01序列推導的,過於抽象):
http://blog.csdn.net/youwuwei2012/article/details/38904839
(好像還有嚴格證明,只不過看不懂QAQ)
然後以這種推導的思路進行更易於理解的證明:
referring to:
http://www.cnblogs.com/jianglangcaijin/p/3443689.html
http://blog.csdn.net/wzq_qwq/article/details/48706151
(圖源:wzq_QwQ,圖爲推廣的模型)
對於卡特蘭數的基礎模型,進棧和出棧的次數相等且爲一定值2n,其中進棧次數爲n且在任意時刻進棧次數不小於出棧次數。考慮一個座標軸的模型,記每一次操作爲右移一格,出棧下移,進棧上移,於是縱座標代表棧內元素個數y,且y恆爲非負整數。根據卡特蘭數的定義,從(0,0)開始移動,終止於(2n,0)點,由此操作數共有
綜上,卡特蘭數的公式爲:
將證明推廣,進棧元素設爲m(m>=n),於是同理可得推廣後的卡特蘭數公式:
。
此題按此公式,拿逆元求一下就好了。一定不能寫錯exgcd!!!
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mod=20100403;
int n,m;
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
int res=exgcd(b,a%b,x,y);
int temp=x;
x=y;
y=temp-y*(a/b);
return res;
}
int inverse(int a)
{
int x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
int C(int m,int n)
{
int res=1;
for(int i=n-m+1;i<=n;i++)
res=1LL*res*i%mod;
for(int i=2;i<=m;i++)
res=1LL*res*inverse(i)%mod;
return res;
}
int main()
{
scanf("%d%d",&n,&m);
cout<<((C(n,m+n)-C(n+1,m+n))%mod+mod)%mod;
return 0;
}