1. 程式人生 > >HDU 5698 瞬間移動(費馬、逆元)

HDU 5698 瞬間移動(費馬、逆元)

題目:

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

Input多組測試資料。 

兩個整數n,m(2n,m100000)n,m(2≤n,m≤100000) 
Output一個整數表示答案Sample Input
4 5
Sample Output
10

首先,很容易求出答案是(m+n-4)!/(m-2)!/(n-2)!
然後就是想辦法打表了。
肯定不是真的把階乘都存起來,因為10000!的十進位制有35660位,100000!的位數就更是多的多。
既然這個題目是模1000000007的,那麼階乘也是可以用模1000000007來存的。
最後只剩下1個問題,在模運算下,如何計算除法。
數論裡面有個專門解決除法的好東西,叫逆元。
根據費馬小定理,用快速冪就可以求出逆元。

程式碼:

#include<iostream>
using namespace std;

int p = 1000000007;
long long fac[200000];
long long anti[100000];

long long get_mi(long long n,int k)
{
	if (k == 0)return 1;
	long long r = get_mi(n, k / 2) % p;
	r = (r*r) % p;
	if (k % 2)r = (r*n) % p;
	return r;
}

void build()
{
	fac[0] = 1;
	anti[0] = 1;
	for (int
i = 1; i < 100000; i++) { fac[i] = (fac[i - 1] * i) % p; anti[i] = get_mi(fac[i], p - 2); //費馬 } for (int i = 100000; i <200000; i++)fac[i] = (fac[i - 1] * i) % p; } int main() { build(); int n, m; while (cin >> n >> m) { long long r = fac[m + n - 4]; r = (r*anti[m - 2]) % p; r =
(r*anti[n - 2]) % p; cout << r << endl; } return 0; }