Problem:
Score : 1500 points

Problem Statement

#nck {
width: 30px;
height: auto;
}

Consider all integers between 1 and 2N, inclusive.
Snuke wants to divide these integers into N pairs such that:

Each integer between 1 and 2N is contained in exactly one of the pairs.

In exactly A pairs, the difference between the two integers is 1.

In exactly B pairs, the difference between the two integers is 2.

In exactly C pairs, the difference between the two integers is 3.

Note that the constraints guarantee that N = A + B + C, thus no pair can have the difference of 4 or more.

Compute the number of ways to do this, modulo 10^9+7.

Constraints

1 ≤ N ≤ 5000

0 ≤ A, B, C

A + B + C = N

Input

The input is given from Standard Input in the following format:

N A B C

Output

Print the answer.

Sample Input 1

3 1 2 0

Sample Output 1

2

There are two possibilities: 1-2, 3-5, 4-6 or 1-3, 2-4, 5-6.

Sample Input 2

600 100 200 300

Sample Output 2

522158867

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>

using namespace std;

const int MOD=1000000007;
int fact[10001];
int ifact[10001];

int powmod(int a, int b)
{
    int ret=1;
    for(; b>0; b/=2)
    {
        if(b&1)
            ret=1LL*ret*a%MOD;
        a=1LL*a*a%MOD;
    }
    return ret;
}

int C(int n, int k)
{
    return 1LL*fact[n]*ifact[k]%MOD*ifact[n-k]%MOD;
}

int solve(int a, int b, int c, int d, int f)
{
    if(c==0)
    {
        if(d==0)
            return C(a+b, a);
        return 0;
    }
    int e=C(d+c-1, d);
    return 1LL*e*C(a+b+c+f, a+b+c)%MOD*C(a+b+c, a+b)%MOD*C(a+b, a)%MOD;
}

int main()
{
    fact[0]=1;
    ifact[0]=1;
    for(int i=1; i<=10000; i++)
    {
        fact[i]=1LL*fact[i-1]*i%MOD;
        ifact[i]=powmod(fact[i], MOD-2);
    }
    int N, A, B, C;
    scanf("%d%d%d%d", &N, &A, &B, &C);
    if(B%2==1)
        return printf("0\n"), 0;
    int ans=0;
    for(int c=0; c<=C; c+=3)
        for(int i=0; i<=min(A, C-c); i++)
            ans=(ans+solve(i, A-i, B/2, C-c-i, c/3))%MOD;
    printf("%d\n", ans);
    return 0;
}