51nod 1119 机器人走方格(费马小定理)
2016-08-16 21:53
211 查看
M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。
Input
Output
Input示例
Output示例
相关问题
一开始我的做法十分的傻逼,就是用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;
}
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;
}
相关文章推荐
- 51nod 1119 机器人走方格 V2 费马小定理求组合数
- 51nod 1119 机器人走方格(费马小定理)
- 【51Nod】1119 - 机器人走方格V2(逆元 & 费马小定理 & 快速幂)
- 51nod 1119 机器人走方格 V2
- 51Nod 1119 机器人走方格 V2
- 51nod 1119:机器人走方格 V2
- 51nod-1119 1119 机器人走方格 V2(组合数学+乘法逆元+快速幂)
- 51nod-【1119 机器人走方格 V2】
- 51nod 1119 机器人走方格 V2
- [51nod-1119]机器人走方格V1 题解
- 51nod 1119 机器人走方格 V2 求大组合取模--逆元
- 51nod 1119 机器人走方格 V2
- 51nod--1119 机器人走方格 V2
- 51nod 1118 机器人走方格 & 1119 机器人走方格 V2(排列组合)
- 机器人走方格 V2 51Nod - 1119 组合数学+逆元
- 51nod 1119 机器人走方格 V2(费马小定理+快速幂 求逆元)
- 51Nod 1119 机器人走方格 组合数学
- 51nod 1118 机器人走方格 解题思路:动态规划 & 1119 机器人走方格 V2 解题思路:根据杨辉三角转化问题为组合数和求逆元问题
- 51nod 1119 机器人走方格 V2 (求组合数__模板)
- 51nod 1119 机器人走方格 (简单数论)