M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。
收起
输入
第1行,2个数M,N,中间用空格隔开。(2 <= m,n <= 1000000)
输出
输出走法的数量 Mod 10^9 + 7。
输入样例
2 3
输出样例
3
题目传送门
刚开始考虑从左上角走到右下角每走一步下一步共有两种选择:向下走或者向右走;所以求出向左走或者向右走共有多少种走法即可。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const long long maxn = 1e9 + 7;
long long m, n;
long long fun(long long x,long long y)
{
if (x == m || y == n) return 0;
else if (x == m - 1 && y == n - 1) return 1;
else
return( (fun(x + 1, y) + fun(x, y + 1))%maxn);
}
int main()
{
cin >> m >> n;
cout << fun(0, 0) << endl;
getchar();
getchar();
}
但由于M,N的取值范围过大,超出题目所要求的时间范围,所以不得不换一种思路。
可以看出在M×N的方格中,从左上角走到右下角一共要走M+N-2个方格,其中向下走M-1个方格,向右走N-1个方格,也就是在M+N-2步中选取M-1或者N-1步有多少种组合方式,即C(M+N-2,min(M-1,N-1))%mod(题目要求输出走法的数量%mod)。
除法取模可以用费马小定理求逆元
根据排列组合的公示,可将原始变为a/b%mod=x(x为最终输出结果),即a/b=x(%mod)
费马小定理:假如p是质数,且(a,MOD)=1,那么 a^(MOD-1) ≡1(%MOD)
假如MOD是质数,且a,MOD互质,那么 a的(MOD-1)次方除以MOD的余数恒等于1
即b^(MOD-1)=1(%MOD)(MOD是质数且与b互质)
可推导出a/b×b^(MOD-1)=x(%MOD)(因为,a%c=x,b%c=y,则a×b%c=x×y)
即a×b^(MOD-2) =x(%MOD),所以x=a×b^(MOD-2)%MOD;可用快速幂求解。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const long long maxn = 1e9 + 7;
long long m, n;
long long quick_pow(long long x, long long y)
{
long long ans = 1;
while (y)
{
if (y % 2)
{
ans = ans * x%maxn;
}
y >>= 1;
x = x * x%maxn;
}
return ans%maxn;
}
int main()
{
cin >> m >> n;
long long t = min(m-1,n-1);
long long ans1 = 1, ans2 = 1;
n = m + n - 2;//由于n在下面已经没有用处,所以可以重新赋值用于其他途径
for (long long i = n; i >= n-t+1; i--)
ans1 = ans1 * i%maxn;
for (long long i = t; i >= 2; i--)
ans2 = ans2 * i%maxn;
long long ans3 = ans1 * quick_pow(ans2, maxn - 2) % maxn;
cout << ans3 << endl;
getchar();
getchar();
}
参考资料
https://blog.youkuaiyun.com/Greenary/article/details/79343963