Problem Statement
We have a large square grid with H rows and W columns. Iroha is now standing in the top-left cell. She will repeat going right or down to the adjacent cell, until she reaches the bottom-right cell.
However, she cannot enter the cells in the intersection of the bottom A rows and the leftmost B columns. (That is, there are A×B forbidden cells.) There is no restriction on entering the other cells.
Find the number of ways she can travel to the bottom-right cell.
Since this number can be extremely large, print the number modulo 10^9+7.
Constraints
- 1≦H,W≦100,000
- 1≦A<H
- 1≦B<W
Input
The input is given from Standard Input in the following format:
H W A B
Output
Print the number of ways she can travel to the bottom-right cell, modulo 10^9+7.
Sample Input 1
2 3 1 1
Sample Output 1
2
Sample Input 2
10 7 3 4
Sample Output 2
3570
题意:H * W的方格图,左下角长A宽B的方格矩阵不能走,问从(1,1)走到(H,W)有多少种方案。
解析:因为方格图比较大,常规dp解法不适用,所以需要数学解法,对于没有限制的方格图n*m,从(1,1)走到(n,m)的方案数其实就是C(n+m-2,n-1),因为从(1,1)走到(n,m)一定是走了n-1个向下,m-1个向右,因此等价于从(n+m-2)里选出(n-1)个向下,因此方案数就是C(n+m-2,n-1)。
因此相当于我们从S先走到 i ,再从 i 走到T,对于每一部分 ,方案数计算方案跟上述相同,因此此时方案数就是C1*C2,对于i+1,i+2,....,W都是同理,累加取模即可。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5,mod=1e9+7;
typedef long long ll;
using i64 = int64_t;
i64 fpow(i64 x, i64 r)
{
i64 result = 1;
while (r)
{
if (r & 1)result = result * x % mod;
r >>= 1;
x = x * x % mod;
}
return result;
}
namespace binom {
i64 fac[N], ifac[N];
int __ = []
{
fac[0] = 1;
for (int i = 1; i <= N - 5; i++)
fac[i] = fac[i - 1] * i % mod;
ifac[N - 5] = fpow(fac[N - 5], mod - 2);
for (int i = N - 5; i; i--)
ifac[i - 1] = ifac[i] * i % mod;
return 0;
}();
inline i64 C(int n, int m)
{
if (n < m || m < 0)return 0;
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
inline i64 A(int n, int m)
{
if (n < m || m < 0)return 0;
return fac[n] * ifac[n - m] % mod;
}
}
using namespace binom;
//以上都是组合数模板
void solve()
{
ll H,W,A,B,ans=0;
scanf("%lld%lld%lld%lld",&H,&W,&A,&B);
B++;//非法矩阵的后一列开始
for(int i=B;i<=W;i++) ans=(ans+C(i+H-A-2,i-1)*C(W-i+1+A-2,A-1))%mod;
printf("%lld\n",ans);
}
int main()
{
int t=1;
//scanf("%d",&t);
while(t--) solve();
return 0;
}