摘抄百度百科:
卡特蘭數又稱卡塔蘭數,英文名Catalan number,是組合數學中一個常出現在各種計數問題中出現的數列。由以比利時的數學家歐仁·查理·卡塔蘭 (1814–1894)命名,其前幾項爲 :
令
卡特蘭數滿足:
這個形式往往是我們運用卡特蘭數的精髓,通常化成這樣的遞推式,就可以運用卡特蘭數的另類公式解題了
另類公式:
題意(HDU5673):機器人從原點開始走,每一步可以選擇不走,向左一步或向右一步,再原點時不能向右走,問走n步後回到原點的方案數是多少。
本題題解:
機器人要麼向左要麼向右或者不動,向左的次數肯定等於向右的次數,設向左的次數爲次,則向右的次數也爲次,不動的次數就爲,則不動的選擇爲
現在剔除了不動點,剩下的都是要動的,分別爲向左次和向右次,因爲在原點時只能向右,所以從第一步開始,每一步累積的向左次數不能超過向右次數,否則就到原點左邊了
把向右走一步看成添加一個左括號,向左走看成添加一個右括號,則問題變成了,有對括號的合法括號序列爲多少個
設爲有對括號的合法括號序列數,因爲每一個左括號唯一對應一個右括號,所以我們從左括號對應第幾個右括號枚舉起,如對應第一個右括號,則左邊括號內還有0對括號,相當於,右邊剩下對合法括號序列,相當於
所以當一個左括號對應第一個右括號時有個合法序列。
當第一個左括號對應第二個右括號時,左邊內還有一對括號的合法序列,所以爲,右邊還剩對括號,所以是
所以當一個左括號對應第二個右括號時有個合法序列。
後面枚舉是一樣的,可以發現這是一個遞推式,而且跟卡特蘭數的遞推式一模一樣。
所以有個不動點的合法情況是
答案即爲
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int MX=2e6+7;
const int mod=1e9+7;
using namespace std;
int p[MX],k[MX];
ll qpow(ll a,ll b,ll MOD=mod){for(ll ans=1;;a=a*a%MOD,b>>=1){if(b&1)ans=ans*a%MOD;if(!b)return ans;}}
ll inv(ll a,ll MOD=mod){return qpow(a,MOD-2,MOD);}
ll __gcm(ll a,ll b){return a*b/__gcd(a,b);}
ll A[MX],B[MX],C[MX];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
A[1]=1;
A[0]=1;
B[0]=1;
B[1]=1;
rep(i,2,MX-1)
{
A[i]=A[i-1]*i%mod;
B[i]=inv(A[i])%mod;
C[i]=B[i]*B[i]%mod*inv(i+1)%mod;
}
C[1]=inv(2);
int T;
cin>>T;
while(T--){
int n;
cin>>n;
ll sum=1;
ll res=0;
for(int i=1;i<=n/2;i++)
{
res=res+C[i]*B[n-2*i]%mod;
if(res>=mod)res-=mod;
}
sum=sum+res*A[n]%mod;
cout<<sum%mod<<endl;
}
}