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 Kotlin (1.0.0) (judge verdict: Accepted)

import java.util.*
import java.math.*

private val readString: ()->String = {readLine()!!}
private val readInt: ()->Int = { readLine()!!.toInt() }
private val readLong: ()->Long = { readLine()!!.toLong() }
private val readListInt: ()->List<Int> = { readLine()!!.split(' ').map(String::toInt) }
private val readListLong: ()->List<Long> = { readLine()!!.split(' ').map(String::toLong) }
private val errPrintln: (String)->Unit = { msg -> System.err.println(msg) }
private val MOD = 1e9.toLong()+7


class LongMod(var num: Long, val MOD: Long = 1e9.toLong()+7) {
    init {
        this.num = (this.num%this.MOD + this.MOD)%this.MOD
    }
    constructor(numStr: String, MOD: Long = 1e9.toLong()+7) :
            this(0L, MOD) {
        if (numStr.isEmpty()) return
        var rv = numStr.reversed()
        var d = 1L
        rv.forEach{ c ->
            this.num += (c - '0') * d
            this.num %= MOD
            d *= 10
            d %= MOD
        }
    }
    override operator fun equals(other: Any?): Boolean {
        if (other !is LongMod) return false
        return this.num % this.MOD == other.num % this.MOD
    }
    operator fun unaryMinus(): LongMod {
        return LongMod(-this.num)
    }
    operator fun plusAssign(other: LongMod): Unit {
        if ((this.num + other.num) >= this.MOD) {
            this.num -= this.MOD
        }
        this.num += other.num
    }
    operator fun minusAssign(other: LongMod): Unit {
        if ((this.num + this.MOD - other.num) >= this.MOD) {
            this.num -= this.MOD
        }
        this.num += this.MOD - other.num
    }
    operator fun timesAssign(other: LongMod): Unit {
        this.num *= other.num
        this.num %= this.MOD
    }
    operator fun plus(other: LongMod): LongMod {
        val res = LongMod(this.num, this.MOD)
        res += other
        return res
    }
    operator fun minus(other: LongMod): LongMod {
        val res = LongMod(this.num, this.MOD)
        res -= other
        return res
    }
    operator fun times(other: LongMod): LongMod {
        val res = LongMod(this.num, this.MOD)
        res *= other
        return res
    }
    tailrec fun pow(n: Long): LongMod {
        if (n == 0L) return LongMod(1L, this.MOD)
        var x = this.pow(n / 2)
        x.timesAssign(x)
        if (n % 2 == 1L) x.timesAssign(this)
        return x
    }
    fun inv(): LongMod {
        return this.pow(this.MOD - 2)
    }
    operator fun divAssign(other: LongMod): Unit {
        this *= other.inv()
    }
    operator fun div(other: LongMod): LongMod {
        val res = LongMod(this.num, this.MOD)
        res /= other
        return res
    }
}
class NckModLongTbl(val N: Int, val MOD: Long = 1e9.toLong()+7) {
    private var fact = arrayOf<LongMod>()
    private var iFact = arrayOf<LongMod>()
    init {
        this.fact = Array<LongMod>(N+1){LongMod(0L, MOD)}
        this.iFact = Array<LongMod>(N+1){LongMod(0L, MOD)}
        this.fact[0] = LongMod(1L, MOD)
        for (i in 1..N) {
            this.fact[i] = this.fact[i-1] * LongMod(i.toLong(), MOD)
        }
        this.iFact[N] = this.fact[N].inv()
        for (i in N downTo 1) {
            this.iFact[i-1] = this.iFact[i] * LongMod(i.toLong(), MOD)
        }
    }
    fun nCkMod(N: Int, K: Int): LongMod {
        if (K < 0 || N < K) return LongMod(0L, MOD)
        return this.fact[N] * this.iFact[K] * this.iFact[N-K]
    }
}


fun solveB(H: Int, W: Int, A: Int, B: Int): Long {
    val tbl = NckModLongTbl(H+W, MOD)

    var res = LongMod(0L, MOD)
    for (i in B until W) {
        res = res + tbl.nCkMod(H-A-1 + i, i) * tbl.nCkMod(A-1 + W-i-1, W-i-1)
    }

    return res.num
}


fun main(args: Array<String>) {
    val (H,W,A,B) = readListInt()

    val ans = solveB(H, W, A, B)

    println(ans)
}