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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;

public class Program
{
    public static long loop;

    static long h;
    static long w;
    static long a;
    static long b;

    static string output;

    public static void Main(string[] args)
    {
        loop = 0;

        Input();
        Proc();
        Output();
    }

    static void Input()
    {
        string[] input = null;

        // スペース区切りの整数の入力(横、個別)
        input = Console.ReadLine().Split(' ');

        h = long.Parse(input[0]);   // 縦
        w = long.Parse(input[1]);   // 横

        a = long.Parse(input[2]);   // 縦
        b = long.Parse(input[3]);   // 横
    }

    static void Proc()
    {
        MathMod mathMod = new MathMod();
        mathMod.ComInit(h + w);

        long sum = 0;

        // 通過点のパターン数ループ
        for (long wRoute = b; wRoute < w; wRoute++)
        {
            loop++;

            long x;
            long y;
            long combination1;
            long combination2;

            // 左上から通過点まで
            x = wRoute;
            y = h - a - 1;
            combination1 = mathMod.Com(x + y, y);

            // 通過点から右下まで
            x = w - wRoute - 1;
            y = a - 1;
            combination2 = mathMod.Com(x + y, y);

            sum = mathMod.Add(sum, mathMod.Mul(combination1 * combination2));
        }

        output = sum.ToString();
    }

    static void Output()
    {
        // 出力
        Console.WriteLine(output);
        output = string.Empty;
    }
}

public class MathMod
{
    public long mod;

    public long[] fac;
    public long[] finv;

    public MathMod(long mod = 1000000000 + 7)
    {
        this.mod = mod;
    }

    public long Add(params long[] values)
    {
        long result = 0;

        foreach (long value in values)
        {
            result += value;
            result %= mod;
            if (result < 0)
            {
                result += mod;
            }
        }

        return result;
    }

    public long Sub(params long[] values)
    {
        long result = 0;

        values[0] *= -1;
        foreach (long value in values)
        {
            result -= value;
            result %= mod;
            if (result < 0)
            {
                result += mod;
            }
        }

        return result;
    }

    public long Mul(params long[] values)
    {
        long result = 1;

        foreach (long value in values)
        {
            result *= value;
            result %= mod;
            if (result < 0)
            {
                result += mod;
            }
        }

        return result;
    }

    public long Inv(long a)
    {
        long b = mod;
        long u = 1;
        long v = 0;

        while (b != 0)
        {
            long t = a / b;
            a -= t * b;
            Swap(ref a, ref b);
            u -= t * v;
            Swap(ref u, ref v);
        }

        u %= mod;
        if (u < 0)
        {
            u += mod;
        }

        return u;
    }

    public long Pow(long a, long n)
    {
        long result = 1;
        while (n > 0)
        {
            if ((n & 1) > 0)
            {
                result = (result * a) % mod;
            }
            a = (a * a) % mod;

            n >>= 1;
        }

        if (result < 0)
        {
            result += mod;
        }
        return result;
    }

    public void ComInit(long max)
    {
        long[] inv = new long[max];

        fac = new long[max];
        finv = new long[max];

        fac[0] = fac[1] = 1;
        finv[0] = finv[1] = 1;
        inv[1] = 1;
        for (int i = 2; i < max; i++)
        {
            fac[i] = fac[i - 1] * i % mod;
            inv[i] = mod - inv[mod % i] * (mod / i) % mod;
            finv[i] = finv[i - 1] * inv[i] % mod;
        }
    }

    public long Com(long n, long k)
    {
        if (n < k)
        {
            return 0;
        }

        if (n < 0 || k < 0)
        {
            return 0;
        }

        long inv = (finv[k] * finv[n - k]) % mod;
        long result = (fac[n] * inv) % mod;
        return result;
    }

    private void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp;
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}