いろはちゃんとマス目 / Iroha and a Grid(AtCoder-1974)

Problem Description

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 109+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 109+7.

Example

Sample Input 1

2 3 1 1

Sample Output 1

2
We have a 2×3 grid, but entering the bottom-left cell is forbidden. The number of ways to travel is two: "Right, Right, Down" and "Right, Down, Right".

Sample Input 2

10 7 3 4

Sample Output 2

3570
There are 12 forbidden cells.

Sample Input 3

100000 100000 99999 99999

Sample Output 3

1

Sample Input 4

100000 100000 44444 55555

Sample Output 4

738162020

题意:有一个区域,大小是 h*w,现在有一个 (1,1) 到 (A,B) 的禁区不能走,现在要在左上角 (1,h) 走到右下角 (w,1),每次只能向右或向下走,问有多少种走法,最后答案对 1E9+7 取模

思路:

首先考虑无禁区的情况:从 (1,h) 走到 (w,1) 总共走 h+w-2 步,而在走到最高一行前,每次都可以选择是否向下走,即可以选择 h-1 次,那么方案数即为 C_{h+w-2}^{h-1}

再考虑有禁区的情况:

每个合法路径都会到达第 h-A 行的 B 之后的某一列上,则每个合法的路径都可以分为从 (1,1) 走到第 h-A 行 B 之后的第 i 列上,与第 h-A 行 B 之后的第 i 列走到 (h,w) 上,然后考虑第 h-A 行 B 之后的第 i 列不能向右移动,那么总的路径就变为 3 段,即:C_{i-1+h-A-1}^{h-A-1}*C_{w-i+A-1}^{w-i},其中,i 从 B+1 到 m

再考虑取模的,由于 1E9+7 是个素数,因此可以考虑使用逆元的方法来求,要注意的是,由于 h 与 w 最大为 1E5,那么预处理阶乘时最大要处理到 w+h,即 2E5。

Source Program

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 200000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;
LL factor[N];
LL PowMod(LL a,LL b){
    LL res=1;
    while(b){
        if(b&1)
            res=(res*a)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return res;
}
LL inv(LL x){
    return PowMod(x,MOD-2);
}
LL C(LL n,LL m){
    return factor[n]*inv(factor[m])%MOD*inv(factor[n-m])%MOD;
}
void init(){
    factor[0]=1;
    for(int i=1;i<=N;i++)
        factor[i]=(factor[i-1]*i)%MOD;
}
int main(){
    init();
    LL h,w,A,B;
    scanf("%lld%lld%lld%lld",&h,&w,&A,&B);
    LL res=0;
    for(LL i=B+1;i<=w;i++){
        LL temp=(C(i-1+h-A-1,h-A-1)*C(w-i+A-1,w-i))%MOD;
        res=(res+temp)%MOD;
    }
    printf("%lld\n",res);
    return 0;
}

 

你可能感兴趣的:(#,AtCoder,#,组合数学——组合数取模)