//code by lynmisakura.wish to be accepted!
/****************************/
#include<iostream>
#include<iomanip>
#include<math.h>
#include<vector>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<bitset>
#include<climits>
#include<set>
#include<bitset>
using namespace std;
/***************************/
typedef long long ll;
typedef vector<ll> vi;
typedef vector<long long> vl;
typedef pair<ll, ll> pi;
typedef vector<pair<ll, ll>> vpi;

//const long long INF = 1LL << 55;

#define itn ll
#define endl '\n'
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define ss second
#define ff first
#define dup(x,y) ((x) + (y) - 1)/(y)
#define mins(x,y) x = min(x,y)
#define maxs(x,y) x = max(x,y)
#define all(x) (x).begin(),(x).end()
#define Rep(n) for(ll i = 0;i < n;i++)
#define rep(i,n) for(ll i = 0;i < n;i++)
#define flush fflush(stdout)
#define rrep(i,n) for(ll i = n - 1;i >= 0;i--)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() )
#define ioboost cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20)
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
ll qp(ll a, ll b) { ll ans = 1; do { if (b & 1)ans = 1ll * ans*a; a = 1ll * a*a; } while (b >>= 1); return ans; }
ll qp(ll a, ll b, ll mo) { ll ans = 1; do { if (b & 1)ans = 1ll * ans*a%mo; a = 1ll * a*a%mo; } while (b >>= 1); return ans; }

#define _GLIBCXX_DEBUG
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl
#define MAX_P 2000100
class combination{
public:
    ll fact[MAX_P]; // n! mod pのテーブル(O(p))
    ll p;
    // factテーブルを初期化する
    combination(ll x = 1000000007){  // x : 余り(1e9 + 7など)
        p = x;
        fact[0] = 1;
        for(ll i = 1;i < MAX_P;i++){
            fact[i] = fact[i - 1] * i % p;
        }
    }
    //拡張ユークリッドの互除法
    ll extgcd(ll a,ll b,ll& x,ll& y){
        ll d = a;
        if(b != 0){
            d = extgcd(b,a%b,y,x);
            y -= (a / b) * x;
        }else{
            x = 1; y = 0;
        }
        return d;
    }
    //mod上の逆元
    ll mod_inverse(ll a,ll m){
        ll x,y;
        extgcd(a,m,x,y); //extgcdが必要
        return (m + x % m) % m;
    }
    //n! = a p^eとしたときの a mod pを求める O(log_p a)
    ll mod_fact(ll n,ll p,ll& e){
        e = 0;
        if(n == 0) return 1;

        //pの倍数の部分を計算
        ll res = mod_fact(n / p,p,e);
        e += n / p;

        //(p - 1)!≡-1なので、(p-1)!^(n/p)はn/pの偶奇だけで計算できる
        if(n / p % 2 != 0) return res * (p - fact[n % p]) % p;
        return res * fact[n % p] % p;
    }

    //mod p 上の二項係数
    ll mod_comb(ll n,ll k){
        if(n < 0 || k < 0|| n < k) return 0;
        ll e1,e2,e3;
        ll a1 = mod_fact(n,p,e1),a2 = mod_fact(k,p,e2),a3 = mod_fact(n - k,p,e3);
        if(e1 > e2 + e3) return 0;
        return a1 * mod_inverse(a2 * a3 % p,p) % p;
    }
};
const int MAX = 2010000;
const int MOD = 1000000007;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < MAX; i++){
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}

// 二項係数計算
long long COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

int main(void){

    ll x,y;cin >> x >> y;
    if((x + y) % 3 != 0){
        cout << 0 << endl;
        return 0;
    }

    ll n = (x + y) / 3;

    x -= n,y -= n;

    // 前処理
    COMinit();

    // 計算例
    cout << COM(n,x) << endl;
}

Measured memory_bytes: 47360