1. 程式人生 > >hdu5968(組合數取模Lucas定理)

hdu5968(組合數取模Lucas定理)

瞬間移動

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1460    Accepted Submission(s): 703


Problem Description 有一個無限大的矩形,初始時你在左上角(即第一行第一列),每次你都可以選擇一個右下方格子,並瞬移過去(如從下圖中的紅色格子能直接瞬移到藍色格子),求到第n行第m列的格子有幾種方案,答案對1000000007取模。


Input 多組測試資料。

兩個整數n,m(2n,m100000)

Output 一個整數表示答案
Sample Input 4 5
Sample Output 10 思路:這個矩形形成了一個楊輝三角,座標(n,m)對應楊輝三角中的座標(n+m-3,m-1),又因為楊輝三角中第n行的m個數可表示為 C(n-1,m-1),所以結果就為C(n+m-4,m-2),再使用Lucas定理求出組合數取模即可。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
#define MOD  1000000007
LL n,m;
LL p=MOD;
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()
{
	
	while(~scanf("%lld%lld",&n,&m))
	{
		printf("%lld\n",Lucas(n+m-4,m-2));
	}
}