您的位置:首页 > 其它

51nod 1119 机器人走方格(费马小定理)

2016-08-16 21:53 211 查看
M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。

Input
第1行,2个数M,N,中间用空格隔开。(2 <= m,n <= 1000000)


Output
输出走法的数量 Mod 10^9 + 7。


Input示例
2 3


Output示例
3


相关问题

一开始我的做法十分的傻逼,就是用dp递推,这个方法只适用于n,m的数值都小于1000 当有1e6的时候,用这个方法就是找死(自己也没看范围),如果范围小就是棋盘DP,范围大就要用到小费马定理。

首先,他的方法数是有规律可寻,规律看如下(每行每列的方案数):

1 1 1   1   1

1 2 3   4   5

1 3 6  10 15

1 4 10 20 35

即可变成

C(0,1) C(0,2) C(0,3)  C(0,4) C(0,5)

C(1,1)C(1,2) C(1,3)  C(1,4) C(1,5)

C(2,2) C(2,3) C(2,4) C(2,5) C(2,6)

C(3,3) C(3,4) C(3,5) C(3,6) C(3,7)

方案数变成了C(n-1,n+m-2)===>(n+m-2)!/((n-1)!(m+1)!)

因为n,m,mod太大,一般求法会爆,所以用了小费马定理(也可以用卢卡斯定理)

小费马定理是 当对任意m有不是mod的倍数的数b,有b^(m-1)=1(mod m)

∴b*b^(m-2)=1  ∴a/b==>a*b^(m-2)  

b^(m-1)就是b的逆元了

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 2000000
#define mod 1000000007
long long int J
;
void init(){
int i;
memset(J,0,sizeof(J));
J[1]=1;
for(i=2;i<=2000000;i++){
J[i]%=mod;
J[i]=(J[i-1]*i)%mod;
J[i]%=mod;
}
return ;
}
long long int mi(long long int n,long long int m){
long long int base=n,r=1;
while(m){
if(m&1)
r=(r*base)%mod;
base=(base*base)%mod;
m>>=1;
}
return r;
}
int main()
{
long long int i,j,n,m;
scanf("%lld %lld",&n,&m);
init();
long long int ans=J[m+n-2];
ans=(ans*mi(J[n-1],mod-2))%mod;
ans=(ans*mi(J[m-1],mod-2))%mod;
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  其他OJ