51nod-1119 机器人走方格(组合数学,离散数学)

1119 机器人走方格V2

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

题解:

  这道题用到的主要是一些数学知识。
  组合数学:可以求出这道题的答案是C(m+n-2, m-1)(一共需要走n+m-2步,从中选出m-1步向下走的就是结果)。
  离散数学:C(m+n-2, m-1)= (n+m-2)!/((n-1)!(m-1)!),涉及到除法取模的问题。定义运算为模1e9+9乘,那么(a/b)%mod = (a*b-1)%mod = (a%mod(b-1)%mod)%mod.所以只需要计算分母在该运算下的逆元即可。
  费马小定理:对于一个素数M,如果gcd(p, m)= 1.那么有p^(M-1)% mod = 1,那么p的逆元就是p^(M-2)(这里的1e9+9是素数可以直接用费马小定理,否则应当找一个比题中mod大的素数求完结果在取一次模),这样就可以求解逆元问题(快速幂)。
     一些细节问题详见代码实现。

代码:

#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const int Max = 2*1e6+5;
const int mod = 1e9+7;//是素数
const int Hash = 10000;
const int INF = 1<<30;
const ll llINF = 1e18;

int m,n;
ll arr[Max];
void init( )
{
    arr[0] = 1;
    for(ll i=1; i<Max; i++)
        arr[i] = (i*arr[i-1])%mod;
}
ll inverse(ll y)//费马小定理求y的逆元
{
    int n = mod-2;
    ll temp = 1;
    while( n/2 )
    {
        if(n % 2)
            temp = (temp*y)%mod;
        y = (y*y)%mod;
        n /= 2;
    }
    return (y*temp)%mod;
}
int main( )
{
    //freopen("input.txt", "r", stdin);
    init( );//预处理出来1百万以内的阶乘结果
    while(~scanf("%d%d",&m, &n))
    {
        ll x = arr[n+m-2];//分子
        ll y = (arr[m-1]*arr[n-1])%mod;//分母
        ll y_ = inverse( y );//求y的乘模逆元
        ll ans = (x*y_)%mod;//代数系统的性质
        cout<<ans<<endl;
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值