HDU 5698 瞬間移動(費馬、逆元)
阿新 • • 發佈:2019-02-17
題目:
有一個無限大的矩形,初始時你在左上角(即第一行第一列),每次你都可以選擇一個右下方格子,並瞬移過去(如從下圖中的紅色格子能直接瞬移到藍色格子),求到第nn行第mm列的格子有幾種方案,答案對1000000007取模。兩個整數n,m(2≤n,m≤100000)n,m(2≤n,m≤100000)
Output一個整數表示答案Sample Input
4 5Sample 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;
}