hdu 5698瞬間移動(組合數取模、盧卡斯定理)

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=5698

數據範圍:

2n,m100000,mod=1000000007。

思路:

打表可以發現這個方法數是一個楊輝三角。

根據楊輝三角的性質,可以知道楊輝三角里面第n行,第m列的數值爲C(n-1,m-1)。

所以我們只要將題目所給的行列轉化一下,然後計算組合數即可。


由於n,m給的範圍比較大。不能直接計算,這是就用到了盧卡斯定理。證明我也沒看懂= =,直接套模板。

盧卡斯定理應用的時候要注意,mod必須爲素數,然後mod不能太大。時間複雜度是O(logp(n)*p)(p爲mod)。

代碼:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef __int64 LL;

LL n,m,p;

LL quick_mod(LL a, LL b)
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}

LL C(LL n, LL m)
{
    if(m > n) return 0;
    LL ans = 1;
    for(int i=1; i<=m; i++)
    {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * quick_mod(b, p-2) % p) % p;
    }
    return ans;
}

LL Lucas(LL n, LL m)
{
    if(m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}

int main()
{
    int T;
     p=1000000007;
        while(~scanf("%I64d%I64d", &n, &m))
        {
            
        LL maxi,mini;
         maxi=n+m-3;
       // if(n==m)maxi+=1;
       
        mini=m-1;
      //  printf("%I64d %I64d\n",maxi,mini);
        printf("%I64d\n", Lucas(maxi-1,mini-1));
    }
    return 0;
}



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