分析
组合数。枚举向右走了B格时向下走的格数[0..H-A-1],之后就相当于无限制位的矩阵走数。设向下走的格数为x,即为无限制位走到(x+1, B)位置,然后向右走一格走出限制列(x+1, B+1)(确保枚举的是第一次走出限制列的位置),最后即为从(x+1,B+1)到(H,W)的无限制位。则该情况下方案数为C(B+x-1, x) * C(H + W - 2 - B - x, H - 1 - x).累加每种情况,注意取模即可。(注意第一个组合数为C(B + x - 1, x))
代码
#define mod 1000000007
#define ll long long
ll exgcd(ll a, ll b, ll & x, ll & y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll inv(ll a, ll MOD) {
ll x, y;
exgcd(a, MOD, x, y);
x = (x % MOD + MOD) % MOD;
return x;
}
ll fac[200010];
void init(int p) {
fac[0] = 1;
for (int i = 1; i <= p; i++) fac[i] = fac[i - 1] * i % mod;
}
ll lucas2(ll n, ll m) {
ll ret = 1, a, b;
while (n && m) {
a = n % mod, b = m % mod;
if (a < b) return 0;
ret = ret * fac[a] % mod * inv(fac[b] * fac[a - b] % mod, mod) % mod;
n /= mod, m /= mod;
}
return ret;
}
int main()
{
ll x, y, n, m;
scanf("%lld%lld%lld%lld", &n, &m, &x, &y);
ll ans = 0;
init(200005);
ll z = y, p = n + m - 2;
for (ll i = 0; i <= n - x - 1; i++) {
ans = ans + lucas2(z + i - 1, i) * lucas2(p - z - i, n - 1 - i) % mod;
ans %= mod;
//printf("1 %lld %lld\n", i, ans);
}
printf("%lld\n", ans);
}