'''

Aは移動関数と同数：xとy方向に合計で3進んでいるから

Bは移動回数の内、(i+1,j+2)を選んだ回数：

1回でx方向には1進み、y方向には2進む

進み方は2通りしかないので、全体の内、1通りを選んだ回数を求めればOK

'''

X,Y=list(map(int,input().split()))

if (X+Y)%3!=0:#まず、条件に合わないケースを除外

  print((0))

  exit()

A=int((X+Y)/3)

B=int((2*Y-X)/3)

if A<0 or B<0:

  print((0))

  exit()

MOD=10**9+7

def comb(n,k):#組合せを求める関数

  tmp=1

  for i in range(n-k+1,n+1):#分子：n*(n-1)*...*(n-k+1)

    tmp*=i

    tmp%=MOD

  for i in range(1,k+1):#分母：k!

    tmp*=pow(i,MOD-2,MOD)#分母なので逆元にする

    tmp%=MOD

  return tmp

ans = comb(A,B)#上記説明の通り。要は組み合わせの問題

print((ans%MOD))
#ika　tako

'''

A.ダメなケースを除外できるか、B.組合せの数を問題に応じて求められるか

階乗や逆元はfor文で求める。

ダメなケースを除外した上で、最終X,Y に行くには、二つの選択肢

(i+1,j+2),(i+2,j+1)の組合せの数を求める。

組合せの数を求める時は、階乗と逆元を使う。

逆元は一通り、全て求めておいて、配列invsに格納して、後で使う。

'''

def prepare(n, MOD):

    f = 1

    for m in range(1, n + 1):

        f = f * m % MOD

    fn = f#n!を求める



    inv = pow(f, MOD - 2, MOD)

    invs = [1] * (n + 1)#[1, 1, 1]のイメージ、逆元？格納テーブル

    invs[n] = inv#配列の一番最後のデータ

    for m in range(n, 1, -1):#n*(n-1)*(n-2)*...と上から掛けている

        inv = inv * m % MOD#逆元を一通り、求めて、配列invsに格納する

        invs[m - 1] = inv

        

    return fn, invs



def solve(x, y):#ダメなケースの除外

    d, m = divmod(x + y, 3)#商と余り

    if m != 0 or x < d or y < d:

    #Xとyの合計は3の倍数、x、yがd移動回数以下はあり得ない（1回1個は進む）

        return 0

    #c = d - x　　これだと範囲外参照でエラー

    c = abs(d - x)#nCr=nC(n-r)、Cの後ろのrと(n-r)を入れ替えても同じ

 

    MOD = 10 ** 9 + 7

    f, invs = prepare(d, MOD)

    return f * invs[c] * invs[d - c] % MOD

  #fはn!、invs[c],invs[d - c] はc!,(d-c)!の逆元？

  #nCr=n!/(r!*(n-r)!)

  

x, y = list(map(int, input().split()))

print((solve(x, y)))
"""
Aは移動関数と同数：xとy方向に合計で3進んでいるから
Bは移動回数の内、(i+1,j+2)を選んだ回数：
1回でx方向には1進み、y方向には2進む
進み方は2通りしかないので、全体の内、1通りを選んだ回数を求めればOK
"""
X, Y = list(map(int, input().split()))
if (X + Y) % 3 != 0:  # まず、条件に合わないケースを除外
    print((0))
    exit()
A = int((X + Y) / 3)
B = int((2 * Y - X) / 3)
if A < 0 or B < 0:
    print((0))
    exit()
MOD = 10**9 + 7


def comb(n, k):  # 組合せを求める関数
    tmp = 1
    for i in range(n - k + 1, n + 1):  # 分子：n*(n-1)*...*(n-k+1)
        tmp *= i
        tmp %= MOD
    for i in range(1, k + 1):  # 分母：k!
        tmp *= pow(i, MOD - 2, MOD)  # 分母なので逆元にする
        tmp %= MOD
    return tmp


ans = comb(A, B)  # 上記説明の通り。要は組み合わせの問題
print((ans % MOD))

# ika　tako
"""
A.ダメなケースを除外できるか、B.組合せの数を問題に応じて求められるか
階乗や逆元はfor文で求める。
ダメなケースを除外した上で、最終X,Y に行くには、二つの選択肢
(i+1,j+2),(i+2,j+1)の組合せの数を求める。
組合せの数を求める時は、階乗と逆元を使う。
逆元は一通り、全て求めておいて、配列invsに格納して、後で使う。
"""


def prepare(n, MOD):
    f = 1
    for m in range(1, n + 1):
        f = f * m % MOD
    fn = f  # n!を求める
    inv = pow(f, MOD - 2, MOD)
    invs = [1] * (n + 1)  # [1, 1, 1]のイメージ、逆元？格納テーブル
    invs[n] = inv  # 配列の一番最後のデータ
    for m in range(n, 1, -1):  # n*(n-1)*(n-2)*...と上から掛けている
        inv = inv * m % MOD  # 逆元を一通り、求めて、配列invsに格納する
        invs[m - 1] = inv
    return fn, invs


def solve(x, y):  # ダメなケースの除外
    d, m = divmod(x + y, 3)  # 商と余り
    if m != 0 or x < d or y < d:
        # Xとyの合計は3の倍数、x、yがd移動回数以下はあり得ない（1回1個は進む）
        return 0
    # c = d - x　　これだと範囲外参照でエラー
    c = abs(d - x)  # nCr=nC(n-r)、Cの後ろのrと(n-r)を入れ替えても同じ
    MOD = 10**9 + 7
    f, invs = prepare(d, MOD)
    return f * invs[c] * invs[d - c] % MOD


# fはn!、invs[c],invs[d - c] はc!,(d-c)!の逆元？
# nCr=n!/(r!*(n-r)!)
x, y = list(map(int, input().split()))
print((solve(x, y)))

+# ika　tako -Aは移動関数と同数：xとy方向に合計で3進んでいるから -Bは移動回数の内、(i+1,j+2)を選んだ回数： -1回でx方向には1進み、y方向には2進む -進み方は2通りしかないので、全体の内、1通りを選んだ回数を求めればOK +A.ダメなケースを除外できるか、B.組合せの数を問題に応じて求められるか +階乗や逆元はfor文で求める。 +ダメなケースを除外した上で、最終X,Y に行くには、二つの選択肢 +(i+1,j+2),(i+2,j+1)の組合せの数を求める。 +組合せの数を求める時は、階乗と逆元を使う。 +逆元は一通り、全て求めておいて、配列invsに格納して、後で使う。 -X, Y = list(map(int, input().split())) -if (X + Y) % 3 != 0:  # まず、条件に合わないケースを除外 -    print((0)) -    exit() -A = int((X + Y) / 3) -B = int((2 * Y - X) / 3) -if A < 0 or B < 0: -    print((0)) -    exit() -MOD = 10**9 + 7 -def comb(n, k):  # 組合せを求める関数 -    tmp = 1 -    for i in range(n - k + 1, n + 1):  # 分子：n*(n-1)*...*(n-k+1) -        tmp *= i -        tmp %= MOD -    for i in range(1, k + 1):  # 分母：k! -        tmp *= pow(i, MOD - 2, MOD)  # 分母なので逆元にする -        tmp %= MOD -    return tmp +def prepare(n, MOD): +    f = 1 +    for m in range(1, n + 1): +        f = f * m % MOD +    fn = f  # n!を求める +    inv = pow(f, MOD - 2, MOD) +    invs = [1] * (n + 1)  # [1, 1, 1]のイメージ、逆元？格納テーブル +    invs[n] = inv  # 配列の一番最後のデータ +    for m in range(n, 1, -1):  # n*(n-1)*(n-2)*...と上から掛けている +        inv = inv * m % MOD  # 逆元を一通り、求めて、配列invsに格納する +        invs[m - 1] = inv +    return fn, invs -ans = comb(A, B)  # 上記説明の通り。要は組み合わせの問題 -print((ans % MOD)) +def solve(x, y):  # ダメなケースの除外 +    d, m = divmod(x + y, 3)  # 商と余り +    if m != 0 or x < d or y < d: +        # Xとyの合計は3の倍数、x、yがd移動回数以下はあり得ない（1回1個は進む） +        return 0 +    # c = d - x　　これだと範囲外参照でエラー +    c = abs(d - x)  # nCr=nC(n-r)、Cの後ろのrと(n-r)を入れ替えても同じ +    MOD = 10**9 + 7 +    f, invs = prepare(d, MOD) +    return f * invs[c] * invs[d - c] % MOD + + +# fはn!、invs[c],invs[d - c] はc!,(d-c)!の逆元？ +# nCr=n!/(r!*(n-r)!) +x, y = list(map(int, input().split())) +print((solve(x, y)))