51nod-1119 1119 机器人走方格 V2(组合数学+乘法逆元+快速幂)

题目链接:

1119 机器人走方格 V2

 

基准时间限制:1 秒
空间限制:131072 KB 
 

 

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的思想是这样的,dp[i][j]=dp[i-1][j]+dp[i][j-1];这种是i,j分别表示i行j列;
我们来转换一下,p[x][j表示第x-j行第j列的方案数,那么p和dp之间的关系是什么样的呢?

p[i][j]=dp[i-j-1][j]+dp[i-j][j-1]=p[i-1][j]+p[i-1][j-1];
p[i][j]=p[i-1][j]+p[i-1][j-1];诶?这个东西好熟悉啊啊啊;让我想想在哪见过......
哈哈哈哈,这就是组合数的递推公式啊,Ci,j=Ci-1,j+Ci-1,j-1;
所以答案就是Cn+m-2,n;
然后就是求乘法逆元和快速幂了;


AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
const ll mod=1e9+7;
ll dp[2*N];
void Iint()
{
    dp[1]=1;
    for(int i=2;i<=200000;i++)
    {
        dp[i]=(dp[i-1]*(ll)i)%mod;
    }
}
ll n,m;
ll fast_pow(ll a,ll b)//快速幂;
{
    ll s=1,base=a;
    while(b)
    {
        if(b&1)
        {
            s*=base;
            s%=mod;
        }
        base *= base;
        base%=mod;
        b=(b>>1);
    }
    return s;
}
int main()
{
    Iint();
     while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        n--;
        m--;
        ll x=dp[n]*dp[m]%mod;
        ll ans=dp[n+m]*fast_pow(x,mod-2)%mod;
        printf("%lld\n",ans);
    }

    return 0;
}

 

 

posted @ 2016-04-18 14:34  LittlePointer  阅读(351)  评论(0编辑  收藏  举报