51Nod1119

题面

(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)! imes (n-1)!}) (=) (frac{(m+n-2)!}{(m-1)! imes (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;
}
原文地址:https://www.cnblogs.com/OFSHK/p/13819148.html