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 Rust (1.15.1) (judge verdict: Accepted)

#![allow(non_snake_case, unused_imports)]

// Input
macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); let mut next = || { iter.next().unwrap() }; input_inner!{next, $($r)*} }; ($($r:tt)*) => { let stdin = std::io::stdin(); let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock())); let mut next = move || -> String{ bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect() }; input_inner!{next, $($r)*} }; }
macro_rules! input_inner { ($next:expr) => {}; ($next:expr, ) => {}; ($next:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($next, $t); input_inner!{$next $($r)*} };}
macro_rules! read_value { ($next:expr, ( $($t:tt),* )) => { ( $(read_value!($next, $t)),* ) }; ($next:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() }; ($next:expr, chars) => { read_value!($next, String).chars().collect::<Vec<char>>() }; ($next:expr, bytes) => { read_value!($next, String).into_bytes() }; ($next:expr, usize1) => { read_value!($next, usize) - 1 }; ($next:expr, $t:ty) => { $next().parse::<$t>().expect("Parse error") }; }

// Module
use std::cmp::{min,max};
use std::collections::{HashSet,BTreeMap,VecDeque};

// Functions
fn init_fact(n: u64, MOD: u64) -> (Vec<u64>, Vec<u64>, Vec<u64>){
    let mut fact = vec![1; n as usize];
    let mut finv = vec![1; n as usize];
    let mut inv  = vec![1; n as usize];
    for i in 2..n as usize{
        fact[i] = (fact[i-1] * i as u64) % MOD;
        inv[i]  = MOD - inv[(MOD as usize)%i] * (MOD/(i as u64))%MOD;
        finv[i] = finv[i-1] * inv[i] % MOD;
    }
    return (fact,finv,inv);
}

fn nCr(n: u64, r: u64, MOD: u64, fact: &Vec<u64>, finv: &Vec<u64>) -> u64{
    if n<r { return 0; }
    return fact[n as usize] * (finv[r as usize] * finv[(n-r) as usize] % MOD) % MOD;
}

// Main
fn main(){
    input!{
        H: u64,
        W: u64,
        A: u64,
        B: u64,
    }
    let modulo = 1_000_000_007;
    let f = init_fact(200_000,modulo);
    let fact = f.0;
    let finv = f.1;

    let mut ans: u64 = 0;
    for i in 0..H-A{
        ans += nCr(i+B-1,i,modulo,&fact,&finv) * nCr(H-i-1+W-B-1,W-B-1,modulo,&fact,&finv);
        ans %= modulo;
    }
    println!("{}", ans);
}