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

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[N];
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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值