#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = a; i < b; i++)
#define pii pair<int, int>
typedef long long ll;

template<int MOD> struct ModInt {
    static const int Mod = MOD; unsigned x; ModInt() : x(0) { }
    ModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
    ModInt(signed long long sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
    int get() const { return (int)x; }
    ModInt &operator+=(ModInt that) { if ((x += that.x) >= MOD) x -= MOD; return *this; }
    ModInt &operator-=(ModInt that) { if ((x += MOD - that.x) >= MOD) x -= MOD; return *this; }
    ModInt &operator*=(ModInt that) { x = (unsigned long long)x * that.x % MOD; return *this; }
    ModInt &operator/=(ModInt that) { return *this *= that.inverse(); }
    ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
    ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
    ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
    ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
    ModInt inverse() const { long long a = x, b = MOD, u = 1, v = 0;
        while (b) { long long t = a / b; a -= t * b; std::swap(a, b); u -= t * v; std::swap(u, v); }
        return ModInt(u); }
    bool operator==(ModInt that) const { return x == that.x; }
    bool operator!=(ModInt that) const { return x != that.x; }
    ModInt operator-() const { ModInt t; t.x = x == 0 ? 0 : Mod - x; return t; }
};
template<int MOD> ostream& operator<<(ostream& st, const ModInt<MOD> a) { st << a.get(); return st; };
template<int MOD> ModInt<MOD> operator^(ModInt<MOD> a, unsigned long long k) {
    ModInt<MOD> r = 1; while (k) { if (k & 1) r *= a; a *= a; k >>= 1; } return r; }
typedef ModInt<1000000007> mint;

static const ll MOD=1e9 + 7;
static const int MAX=7e5 + 10;
const int MAX_N = 7e5 + 10;


ll fact[MAX], fact_inv[MAX];

//繰り返し二乗法
ll power(ll a, ll b){
    ll res = 1;
    while(b > 0){
        if(b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}

ll comb(ll n, ll r){
    return (fact[n] * fact_inv[r]) % MOD * fact_inv[n-r] % MOD;
}

long long modinv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m;
    if (u < 0) u += m;
    return u;
}//mod mでの逆元aを計算

long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}


int main(){
    ll X, Y; cin >> X >> Y;
        fact[0] = 1;
    //階乗計算(O(n))
    for(int i = 0; i < MAX_N; i++) fact[i+1] = fact[i] * (i+1)%MOD;
    fact_inv[MAX_N] = power(fact[MAX_N], MOD - 2);
    //逆元計算(O(logp + n))
    for(int i = MAX_N - 1; i >= 0; i--) fact_inv[i] = fact_inv[i+1]%MOD*(i+1)%MOD;
    //あとはcomb(n,r)に値を突っ込めば良い

    if((X + Y) % 3 != 0) cout << 0 << endl;
    else{
        ll N = (X + Y) / 3;
        X -= N;
        Y -= N;
        if(X < 0 || Y < 0) cout << 0 << endl;
        else{
            cout << comb(N, X) << endl;
        }
    }
}

Measured memory_bytes: 11136