浏览器标题切换
浏览器标题切换end

51Nod1119 - 机器人走方格 V2 - 排列组合推公式+逆元+快速幂

题面

\(M\) x \(N\) 的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。

思路

如果给出的数据较小,可以直接DP写(详情见https://www.cnblogs.com/OFSHK/p/13817688.html),

但是本题的数据过大,连dp的数组都无法开,所以我们要想办法转化一下。

\(m\) x \(n\) 的图中,我们需要从从 \(m+n\) 步中选出 \(m\) 步向下走或 \(n\) 步向右走,所以总共有 \(C(m+n,m)=C(m+n,n)\) 种组合数(也就是路线

数)。

转化成题目给我们的就是 \(C(m-1+n-1, m-1)\) \(=\) \(\frac{(m-1+n-1)!}{(m-1)! \times (n-1)!}\) \(=\) \(\frac{(m+n-2)!}{(m-1)! \times (n-1)!}\)

然后针对其中的阶乘,主函数开始的时候预处理一下就行,涉及到逆元的直接利用快速幂求解即可。

求组合数(取模)的两种方法:https://www.zybuluo.com/ArrowLLL/note/713749

AC代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f

const ll mod=1e9+7;
int m,n;
ll a[2000010];

ll ksm(ll x,int nn)  // **快速幂写错了
{
    ll res=1;
    while(nn)
    {
        if(nn&1)
            res=res*x%mod;
        x=x*x%mod;
        nn>>=1;
    }
    return res;
}

int main()
{
    cin>>n>>m;
    a[1]=1;
    for(int i=2;i<=n+m-2;i++)
        a[i]=(a[i-1]*i)%mod; // 阶乘
    ll x=a[n+m-2],y=a[n-1]*a[m-1]%mod;
    cout<<x*ksm(y,mod-2)%mod<<endl;
    return 0;
}
posted @ 2020-10-15 10:38  抓水母的派大星  阅读(171)  评论(0编辑  收藏  举报