2月27日 grid(卡特蘭數+費馬小定理求乘法逆元)

一道組合問題,catalan數可以計算入棧出棧合法序列數,具體推導可以參考專題博客。
求逆元主要是因爲取模運算(catalan數很大)中含有除法,這裏用費馬小定理求乘法逆元,ap11(modp) ,所以有ap2a1(modp) ,即ap2modp=a1 ,用快速冪求解。
問題描述:
度度熊最近很喜歡玩遊戲。這一天他在紙上畫了一個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,第一次忘記了=號,死循環。

發佈了50 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章