Problem:
Score : 1600 points

Problem Statement

A + B balls are arranged in a row.
The leftmost A balls are colored red, and the rightmost B balls are colored blue.

You perform the following operation:

First, you choose two integers s, t such that 1 \leq s, t \leq A + B.

Then, you repeat the following step A + B times:
In each step, you remove the first ball or the s-th ball (if it exists) or the t-th ball (if it exists, all indices are 1-based) from left in the row, and give it to Snuke.

In how many ways can you give the balls to Snuke?
Compute the answer modulo 10^9 + 7.

Here, we consider two ways to be different if for some k, the k-th ball given to Snuke has different colors.
In particular, the choice of s, t doesn't matter.
Also, we don't distinguish two balls of the same color.

Constraints

1 \leq A, B \leq 2000

Input

Input is given from Standard Input in the following format:

A B

Output

Print the answer.

Sample Input 1

3 3

Sample Output 1

20

There are 20 ways to give 3 red balls and 3 blue balls.
It turns out that all of them are possible.

Here is an example of the operation (r stands for red, b stands for blue):

You choose s = 3, t = 4.

Initially, the row looks like rrrbbb.

You remove 3rd ball (r) and give it to Snuke. Now the row looks like rrbbb.

You remove 4th ball (b) and give it to Snuke. Now the row looks like rrbb.

You remove 1st ball (r) and give it to Snuke. Now the row looks like rbb.

You remove 3rd ball (b) and give it to Snuke. Now the row looks like rb.

You remove 1st ball (r) and give it to Snuke. Now the row looks like b.

You remove 1st ball (b) and give it to Snuke. Now the row is empty.

This way, Snuke receives balls in the order rbrbrb.

Sample Input 2

4 4

Sample Output 2

67

There are 70 ways to give 4 red balls and 4 blue balls.
Among them, only bbrrbrbr, brbrbrbr, and brrbbrbr are impossible.

Sample Input 3

7 9

Sample Output 3

7772

Sample Input 4

1987 1789

Sample Output 4

456315553

Solution in Rust (1.15.1) (judge verdict: Accepted)

const MOD: u64 = 1_000_000_007;

fn mod_pow(r: u64, mut n: usize) -> u64 {
    let mut t = 1;
    let mut s = r;
    while n > 0 {
        if n & 1 == 1 {
            t = t * s % MOD;
        }
        s = s * s % MOD;
        n >>= 1;
    }
    t
}

fn run() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let mut it = s.trim().split_whitespace();
    let a: usize = it.next().unwrap().parse().unwrap();
    let b: usize = it.next().unwrap().parse().unwrap();
    let mut comb = vec![vec![]; b + 1];
    comb[0] = vec![1, 0];
    for i in 1..(b + 1) {
        comb[i] = vec![1; i + 1];
        for j in 1..i {
            comb[i][j] = (comb[i - 1][j - 1] + comb[i - 1][j]) % MOD;
        }
    }
    let mut g1 = vec![vec![1; b + 1]; a + 1];
    for i in 1..(a + 1) {
        for j in 1..(b + 1) {
            if i >= j {
                g1[i][j] = mod_pow(2, j);
            } else {
                g1[i][j] = (g1[i - 1][j] + comb[j][i]) % MOD;
            }
        }
    }
    let mut f1 = vec![vec![1; b + 1]; a + 1];
    for i in 1..(a + 1) {
        for j in 1..(b + 1) {
            f1[i][j] = (f1[i - 1][j] + g1[i][j - 1]) % MOD;
        }
    }
    let mut ans = 0;
    for i in 0..(a + 1) {
        let a = a - i;
        let b = b - 1;
        if a >= b {
            for j in 0..(b + 1) {
                ans += comb[b][j] * f1[a - (b - j)][b - j] % MOD;
            }
        } else {
            for j in 0..(a + 1) {
                ans += comb[b][j] * f1[a - j][j] % MOD;
            }
        }
    }
    ans %= MOD;
    println!("{}", ans);
}

fn main() {
    run();
}