有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
Input
单组测试数据。
两个整数n,m(2<=n,m<=100000)
Output
一个整数表示答案。
Input示例
4 5
Output示例
10
思路:
从左上角走到n行m列最多需要min(n-2, m-2) + 1步。因此所有的可能是C(n-2, i) * C(m-2, i),(0 =< i <= min(n-2, m-2) + 1)。
计算逆元时用递推公式inv[i] = inv[i+1] * (i+1)%mod。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef long long int ll;
const ll MOD = 1e9 + 7;
const int MAXN = 100100;
ll fac[MAXN];
ll inv[MAXN];
ll pow(ll a, ll i)
{
ll result = 1;
while (i)
{
if (i & 1)
{
result = (result * a) % MOD;
}
i >>= 1;
a = (a * a) % MOD;
}
return result;
}
void init()
{
fac[0] = 1;
inv[0] = 1;
for (ll i = 1; i < MAXN; i++)
{
fac[i] = (fac[i-1] * i) % MOD;
}
inv[MAXN-1] = pow(fac[MAXN-1], MOD-2);
for (ll i = MAXN - 2; i > 0; i--)
{
inv[i] = (inv[i+1] * (i + 1)) % MOD;
}
}
ll C(ll n, ll m)
{
if (m > n)
{
return 0;
}
return ((fac[n] * inv[n-m] % MOD) * inv[m]) % MOD;
}
int main()
{
int n, m;
cin >> n >> m;
init();
ll result = 0;
for (int i = 0; i <= min(n, m) - 2; i++)
{
result = (result + C(n-2, i) * C(m-2, i) % MOD) % MOD;
}
cout << result << endl;
return 0;
}