AtCoder Beginner Contest 042--D - Iroha and a Grid(排列组合)

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
  • 1≦B

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)

AtCoder Beginner Contest 042--D - Iroha and a Grid(排列组合)_第1张图片

因此相当于我们从S先走到 i ,再从 i 走到T,对于每一部分 ,方案数计算方案跟上述相同,因此此时方案数就是C1*C2,对于i+1,i+2,....,W都是同理,累加取模即可。

#include 
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;
}

你可能感兴趣的:(算法,c++,c语言)