一道組合問題,catalan數可以計算入棧出棧合法序列數,具體推導可以參考專題博客。
求逆元主要是因爲取模運算(catalan數很大)中含有除法,這裏用費馬小定理求乘法逆元,
問題描述:
度度熊最近很喜歡玩遊戲。這一天他在紙上畫了一個2行N列的長方形格子。他想把1到2N這些數依次放進去,但是爲了使格子看起來優美,他想找到使每行每列都遞增的方案。不過畫了很久,他發現方案數實在是太多了。度度熊想知道,有多少种放數字的方法能滿足上面的條件?
Input
第一行爲數據組數T(1<=T<=100000)。
然後T行,每行爲一個數N(1<=N<=1000000)表示長方形的大小。
Output
對於每組數據,輸出符合題意的方案數。由於數字可能非常大,你只需要把最後的結果對1000000007取模即可。
Sample Input
2
1
3
Sample Output
Case #1:
1
Case #2:
5
代碼:
#include<cstdio>
#define ll long long
ll cata[1000002];
#define MAXNUM 1000000
#define mod 1000000007
ll fast_pow(ll a, ll b, ll p)
{
a %= p;
ll tmp = 1;
while (b)
{
if (b & 1)tmp = (tmp*a) % p;
a = (a*a) % p;
b >>= 1;
}
return tmp;
}
ll inv(ll a, ll p)
{
return fast_pow(a, p - 2, p);
}
void ini()
{
cata[0] = 1;
for (ll i = 0; i <MAXNUM; i++)
{
cata[i + 1] = ((cata[i] * (4 * i + 2)) % mod*inv(i+2,mod))%mod;
}
}
int main()
{
ll n,N;
scanf("%lld", &n);
ini();
for (ll i = 1; i <= n; i++)
{
scanf("%lld", &N);
printf("Case #%lld:\n%lld\n",i, cata[N]);
}
return 0;
}
注意幾點:
1 一次性初始化,否則會tle。
2 long long型有必要
3 快速冪注意b>>=1,第一次忘記了=號,死循環。