摘抄百度百科:
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名,其前几项为 :
1
,
1
,
2
,
5
,
14
,
42
,
132
,
429
,
1430
,
4862
,
16796
,
58786
,
208012
,
742900
,
2674440
,
9694845
,
35357670
,
129644790
,
477638700
,
1767263190
,
6564120420
,
24466267020
,
91482563640
,
343059613650
,
1289904147324
,
4861946401452
,
.
.
.
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...
1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700,1767263190,6564120420,24466267020,91482563640,343059613650,1289904147324,4861946401452,...
令
h
(
0
)
=
1
,
h
(
1
)
=
1
h(0)=1,h(1)=1
h(0)=1,h(1)=1
卡特兰数满足:
h
(
n
)
=
∑
i
=
0
n
−
1
h
(
i
)
⋅
h
(
n
−
i
−
1
)
h(n)=\sum\limits_{i=0}^{n-1}h(i)\cdot h(n-i-1)
h(n)=i=0∑n−1h(i)⋅h(n−i−1)
这个形式往往是我们运用卡特兰数的精髓,通常化成这样的递推式,就可以运用卡特兰数的另类公式解题了
另类公式:
h
(
n
)
=
C
(
2
n
,
n
)
n
+
1
=
C
(
2
n
,
n
)
−
C
(
2
n
,
n
+
1
)
h(n)=\frac{C(2n,n)}{n+1}=C(2n,n)-C(2n,n+1)
h(n)=n+1C(2n,n)=C(2n,n)−C(2n,n+1)
题意(HDU5673):机器人从原点开始走,每一步可以选择不走,向左一步或向右一步,再原点时不能向右走,问走n步后回到原点的方案数是多少。
本题题解:
机器人要么向左要么向右或者不动,向左的次数肯定等于向右的次数,设向左的次数为
i
i
i次,则向右的次数也为
i
i
i次,不动的次数就为
n
−
2
⋅
i
n-2\cdot i
n−2⋅i,则不动的选择为
C
(
n
,
n
−
2
⋅
i
)
C(n,n-2\cdot i)
C(n,n−2⋅i)
现在剔除了不动点,剩下的都是要动的,分别为向左
i
i
i次和向右
i
i
i次,因为在原点时只能向右,所以从第一步开始,每一步累积的向左次数不能超过向右次数,否则就到原点左边了
把向右走一步看成添加一个左括号,向左走看成添加一个右括号,则问题变成了,有
i
i
i对括号的合法括号序列为多少个
设
h
(
n
)
h(n)
h(n)为有
n
n
n对括号的合法括号序列数,因为每一个左括号唯一对应一个右括号,所以我们从左括号对应第几个右括号枚举起,如对应第一个右括号,则左边
(
)
()
()括号内还有0对括号,相当于
h
(
0
)
h(0)
h(0),右边剩下
n
−
1
n-1
n−1对合法括号序列,相当于
h
(
n
−
1
)
h(n-1)
h(n−1)
所以当一个左括号对应第一个右括号时有
h
(
0
)
⋅
h
(
n
−
1
)
h(0)\cdot h(n-1)
h(0)⋅h(n−1)个合法序列。
当第一个左括号对应第二个右括号时,左边
(
)
()
()内还有一对括号的合法序列,所以为
h
(
1
)
h(1)
h(1),右边还剩
n
−
2
n-2
n−2对括号,所以是
h
(
n
−
2
)
h(n-2)
h(n−2)
所以当一个左括号对应第二个右括号时有
h
(
1
)
⋅
h
(
n
−
2
)
h(1)\cdot h(n-2)
h(1)⋅h(n−2)个合法序列。
后面枚举是一样的,可以发现这是一个递推式,而且跟卡特兰数的递推式一模一样。
所以有
n
−
2
i
n-2i
n−2i个不动点的合法情况是
C
(
n
,
n
−
2
⋅
i
)
⋅
h
(
i
)
C(n,n-2\cdot i)\cdot h(i)
C(n,n−2⋅i)⋅h(i)
答案即为
∑
i
=
0
n
/
2
C
(
n
,
n
−
2
⋅
i
)
h
(
i
)
\sum\limits_{i=0}^{n/2}C(n,n-2\cdot i)h(i)
i=0∑n/2C(n,n−2⋅i)h(i)
#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;
}
}