HDU-5698 瞬间移动(杨辉三角 逆元 快速幂)

瞬间移动
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2538 Accepted Submission(s): 1105

Problem Description
有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
HDU-5698 瞬间移动(杨辉三角 逆元 快速幂)

Input
多组测试数据。

两个整数n,m(2≤n,m≤100000)

Output
一个整数表示答案

Sample Input
4 5

Sample Output
10

思路: 找规律,可以发现是一个杨辉三角,然后就可以得到公式C(n+m-4,m-2)。逆元求解!!!

#include<bits/stdc++.h>

using namespace std;
#define ll long long
const long long mod=1000000007;
const int maxn=2e5+7;

ll fac[maxn*2],inv_fac[maxn*2];

ll quickpow(ll x,ll n){
    ll res=1;
    x=x%mod;
    while(n){
        if(n&1)res=(res*x)%mod;
        n>>=1;
        x=(x*x)%mod;
    }
    return res;
}


void init(){
    fac[0]=1;
    for(int i=1;i<=maxn;i++) fac[i]=(fac[i-1]*i)%mod;
    inv_fac[maxn]=quickpow(fac[maxn],mod-2);
    for(int i=maxn-1;i>=0;i--) inv_fac[i]=(inv_fac[i+1]*(i+1))%mod;
}

ll C(int n,int m){
    if(n < 0 || m < 0 || m > n) return 0;
    if(m == 0 || m == n) return 1;
    return fac[n]*inv_fac[n-m]%mod*inv_fac[m]%mod;
}

int n,m,k,T;

int main(){
    init();
    int n,m;
    while(cin>>n>>m){
        cout<<C(m+n-4,m-2)%mod<<endl;
    }
    return 0;
}