Problem:
Score : 400 points

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

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

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String args[]) {
        try (Scanner in = new Scanner(System.in)) {
            int H = in.nextInt();
            int W = in.nextInt();
            int A = in.nextInt();
            int B = in.nextInt();

            boolean[] canUseH = new boolean[H];
            Arrays.fill(canUseH, true);
            for (int i = 0; i < A; i++) {
                canUseH[H - 1 - i] = false;
            }
            boolean[] canUseW = new boolean[W];
            Arrays.fill(canUseW, true);
            for (int i = 0; i < B; i++) {
                canUseW[i] = false;
            }

            long mod = (long) (1e9 + 7);

            long[] w2 = new long[W];
            for (int w = B; w < W; w++) {
                int r = H - A - 1 - (w - B);
                int c = B + (w - B);
                w2[w] = modComb(r + c, r, mod);
            }
            long res = 0;
            for (int w = B; w < W; w++) {
                int r = A + (w - B);
                int c = W - w - 1;
                res += (w2[w] * modComb(r + c, r, mod)) % mod;
                res %= mod;
            }
            System.out.println(res);

        }
    }

    public static final long modComb(long n, long k, long p) {
        if (n < 0 || k < 0 || n < k) {
            return 0;
        }
        long[] e1 = new long[1];
        long[] e2 = new long[1];
        long[] e3 = new long[1];
        long a1 = modFact(n, p, e1);
        long a2 = modFact(k, p, e2);
        long a3 = modFact(n - k, p, e3);
        if (e1[0] > e2[0] + e3[0]) {
            return 0;
        }
        return (a1 * modInverseByFermatsLittleTheorem((a2 * a3) % p, p)) % p;
    }

    private static final int MAX_P = (int) 1e6;
    private static final long[] fact = new long[MAX_P];
    private static final boolean[] first = new boolean[] { true, };

    private static final long modFact(long n, long p, long[] e) {
        if (first[0]) {
            first[0] = false;
            fact[0] = 1;
            for (int i = 1; i < fact.length; i++) {
                fact[i] = (int) ((i * fact[i - 1]) % p);
            }
        }

        e[0] = 0;
        if (n == 0) {
            return 1;
        }

        long res = modFact(n / p, p, e);
        e[0] += n / p;

        if ((n / p) % 2 != 0) {
            return res * (p - fact[(int) (n % p)]) % p;
        }

        return res * fact[(int) (n % p)] % p;
    }

    private static final long modPow(long x, long n, long modulo) {
        long res = 1L;
        while (n > 0) {
            if ((n & 1L) != 0) {
                res = res * x % modulo;
            }
            x = x * x % modulo;
            n >>= 1;
        }
        return res;
    }

    private static long modInverseByFermatsLittleTheorem(long x, long modulo) {
        return modPow(x, modulo - 2, modulo);
    }

}