srupのメモ帳

競プロで解いた問題や勉強したことを記録していくメモ帳

ABC 034 C - 経路

問題

問題概要

道順の総数

解法

高校数学でやった気がする。
(w + h - 2)! / ((w-1)! * (h-1)!)
の値を求めるだけでよい。ただ、割り算が入った形の計算式で、modを取らないといけないので、逆元だったり、フェルマーの小定理を使って求めればいい。

ミス

なし。

コード

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vint;
typedef pair<int,int> pint;
typedef vector<pint> vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define all(v) (v).begin(),(v).end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
const int MOD = 1e9 + 7;
const int INF = 1e9;

const int MAX_N = 2000000;
ll inv[MAX_N + 10];
ll fac[MAX_N + 10], facInv[MAX_N + 10];
class MATH{
public:
    MATH(){
        inverse();
        factroial();
    }
    ll nCk(ll n, ll k){// n! / k!*(n-k)!
        if(k < 0 || k > n) return 0;
        ll ret = fac[n];
        (ret *= facInv[k]) %= MOD;
        (ret *= facInv[n - k]) %= MOD;
        return ret;
    }
    ll nHk(ll n, ll k){// nHk = n+k-1 C k = (n+k-1)! / k! * (n-1)!
        if(n == 0 && k == 0) return 1;
        ll ret = fac[n + k - 1];
        (ret *= facInv[k]) %= MOD;
        (ret *= facInv[n - 1]) %= MOD;
        return ret;
    }
    ll nPk(ll n, ll k){//nPk = n! / (n-k)!
        if(k < 0 || k > n) return 0;
        ll ret = fac[n];
        (ret *= facInv[n - k]) %= MOD;
        return ret;
    }
private:
    void inverse(void){
        inv[1] = 1;
        for (int i = 2; i <= MAX_N; ++i){
            // inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD;
            inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
        }
    }
    void factroial(void){
        fac[0] = facInv[0] = 1;
        for (int i = 1; i <= MAX_N; ++i){
            fac[i] = (fac[i - 1] * i) % MOD;
            facInv[i] = (facInv[i - 1] * inv[i]) % MOD;
        }
    }
};

int main(void){
    int w, h; cin >> w >> h;
    // (w + h  - 2)! / ((w-1)! * (h-1)!)
    MATH ma;
    cout << ma.nCk(w + h - 2, w - 1) << endl;
    return 0;
}