瞬间移动
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 192 Accepted Submission(s): 99
Problem Description
有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
Input
多组测试数据。
两个整数n,m(2 <= n, m <= 100000)
两个整数n,m(2 <= n, m <= 100000)
Output
一个整数表示答案
Sample Input
4 5
Sample Output
10
Source
解析:首先可推出公式为C(n+m-4, n-2)对1000000007取模。接下来问题就转化为计算C(n+m-4, n-2) % 1000000007,而C(n+m-4, n-2) = (n+m-4)! / ((n-2)! * (m-2)!) % 1000000007,故需要求 (n-2)! 和 (m-2)! 的逆元。因为MOD = 1000000007为素数,则对应的逆元分别为 (n-2)!MOD-2 % MOD、(m-2)!MOD-2 % MOD。
最终结果为 (n+m-4)! * (n-2)!MOD-2 % MOD * (m-2)!MOD-2 % MOD。
1 #include <cstdio> 2 3 const int MOD = 1000000007; 4 int n, m; 5 long long f[200010]; 6 7 //求阶乘 8 void init() 9 { 10 f[0] = 1; 11 for(int i = 1; i <= 200000; ++i){ 12 f[i] = f[i-1]*i%MOD; 13 } 14 } 15 16 long long quickpowmod(long long x, long long y) 17 { 18 long long ret = 1; 19 while(y){ 20 if(y&1) 21 ret = ret*x%MOD; 22 x = x*x%MOD; 23 y >>= 1; 24 } 25 return ret; 26 } 27 28 int main() 29 { 30 init(); 31 while(~scanf("%d%d", &n, &m)){ 32 printf("%I64d ", f[n+m-4]*quickpowmod(f[n-2], MOD-2)%MOD*quickpowmod(f[m-2], MOD-2)%MOD); 33 } 34 return 0; 35 }
1000000007