CodeEff/ECCO huggingface dataset:
# Original solution
import sys
input = sys.stdin.readline

MOD = 1000000007

def comb_mod(n, r, mod):
    if n < r:
        return 0
    elif n < 0 or r < 0:
        return 0
    else:
        fac = [1, 1]
        finv = [1, 1]
        inv = [0, 1]
        for i in range(2, n + 1):
            fac.append(fac[-1] * i % mod)
            inv.append(-inv[mod % i] * (mod // i) % mod)
            finv.append((finv[-1] * inv[-1]) % mod)

        return int(fac[n] * finv[r] * finv[n - r] % mod)

x, y = list(map(int, input().split()))
m = int((x * 2 - y) / 3)
n = int(x - 2 * m)

if (x + y) % 3 != 0:
    print((0))
else:
    print((comb_mod(n + m, n, MOD)))


# Optimized solution
import sys

sys.setrecursionlimit(10 ** 7)
input = sys.stdin.readline
f_inf = float('inf')
mod = 10 ** 9 + 7


class CmbMod:
    def __init__(self, n, p):
        """
        二項係数nCr(n個の区別できるものからr個のものを選ぶ組み合わせの数)をpで割った余りを求める
        """
        self.n = n
        self.p = p
        self.fact = [1, 1]
        self.factinv = [1, 1]
        self.inv = [0, 1]

    def cmb_mod(self, n, r):
        """
        二項係数nCr(mod p)をO(r)にて計算。nが大きいがrは小さい時に使用。
        """
        numer, denom = 1, 1
        for i in range(r):
            numer = (numer * (n - i)) % self.p
            denom = (denom * (i + 1)) % self.p
        return (numer * pow(denom, self.p - 2, self.p)) % self.p

    def prep(self):
        """
        二項係数nCr(mod p)をO(1)で求める為の前処理をO(N)にて実行。
        """
        for i in range(2, self.n + 1):
            self.fact.append((self.fact[-1] * i) % self.p)
            self.inv.append((-self.inv[self.p % i] * (self.p // i)) % self.p)
            self.factinv.append((self.factinv[-1] * self.inv[-1]) % self.p)

    def cmb_mod_with_prep(self, n, r):
        """
        二項係数nCr(mod p)をO(1)で求める。事前にprepを実行する事。
        """
        if (r < 0) or (n < r):
            return 0
        r = min(r, n - r)
        return self.fact[n] * self.factinv[r] * self.factinv[n - r] % self.p


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

    cnt = (X + Y) // 3
    left = 0
    right = 0
    for i in range(cnt):
        if (i * 1 + (cnt - i) * 2 == X and i * 2 + (cnt - i) * 1 == Y) or (
                i * 1 + (cnt - i) * 2 == Y and i * 2 + (cnt - i) * 1 == X):
            left = i
            right = cnt - i
            break
    else:
        print((0))
        exit()

    cmb = CmbMod(cnt, mod)
    res = cmb.cmb_mod(cnt, min(left, right))
    print(res)


if __name__ == '__main__':
    resolve()
# Original solution
import math
X,Y = list(map(int,input().split()))
a,b = (2*Y-X)/3,(2*X-Y)/3
n = 10**9+7
nCr={}
def cmb(n, r):
    if n - r < r: r = n - r
    if r == 0: return 1
    if r == 1: return n

    numerator = [n - r + k + 1 for k in range(r)]
    denominator = [k + 1 for k in range(r)]

    for p in range(2,r+1):
        pivot = denominator[p - 1]
        if pivot > 1:
            offset = (n - r) % p
            for k in range(p-1,r,p):
                numerator[k - offset] /= pivot
                denominator[k] /= pivot

    result = 1
    for k in range(r):
        if numerator[k] > 1:
            result *= int(numerator[k])

    return result
def count():
  if not (a//1 == a and b//1==b):
    return 0
  else:
    ahat = int(a%n)
    bhat = int(b%n)
    return cmb(ahat+bhat,ahat)


print((int(count())%(10**9+7)))

# Optimized solution
import math
X,Y = list(map(int,input().split()))
a,b = (2*Y-X)/3,(2*X-Y)/3
n = 10**9+7
def cmb(n, r, mod=10**9+7):
    n1, r = n+1, min(r, n-r)
    numer = denom = 1
    for i in range(1, r+1):
        numer = numer * (n1-i) % mod
        denom = denom * i % mod
    return numer * pow(denom, mod-2, mod) % mod
def count():
  if not (a//1 == a and b//1==b):
    return 0
  else:
    ahat = int(a%n)
    bhat = int(b%n)
    return cmb(ahat+bhat,ahat)


print((int(count())%(10**9+7)))
# Original solution
def comb(n, k, MOD):
    if n < k or n < 0 or k < 0:
        return 0
    k = min(k, n - k)
    if k == 0:
        return 1
    iinv = [1] * (k + 1)
    ans = n
    for i in range(2, k + 1):
        iinv[i] = MOD - iinv[MOD % i] * (MOD // i) % MOD
        ans *= (n + 1 - i) * iinv[i] % MOD
        ans %= MOD
    return ans

mm = 10**9 + 7
x, y = (int(x) for x in input().split())
ans = 0
if (x - 2*y) % 3 == 0:
    beta = (x - 2*y) // -3
    alpha = y - 2*beta
    ans = comb(alpha+beta, beta, mm)
print(ans)

# Optimized solution
# https://www.geeksforgeeks.org/compute-ncr-p-set-3-using-fermat-little-theorem/
def comb(n, r, p): 
    num = den = 1 
    for i in range(r): 
        num = (num * (n - i)) % p 
        den = (den * (i + 1)) % p 
    return (num * pow(den,  p - 2, p)) % p 
  
m = 10**9 + 7
x, y = (int(x) for x in input().split())
ans = 0
if (x - 2*y) % 3 == 0:
    beta = (x - 2*y) // -3
    alpha = y - 2*beta
    ans = comb(alpha+beta, max(alpha, beta), m)
print(ans)
# Original solution
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):
    tmp*=i
    tmp%=MOD
  for i in range(1,k+1):
    tmp*=pow(i,MOD-2,MOD)
    tmp%=MOD
  return tmp
ans = comb(A,B)
print((ans%MOD))

# Optimized solution
#ika　tako
def prepare(n, MOD):
    f = 1
    for m in range(1, n + 1):
        f = f * m % MOD
        #print(f)
    fn = f#n!を求める
    #print(fn)
 
    #print(f)
    inv = pow(f, MOD - 2, MOD)
    #print(inv)
    invs = [1] * (n + 1)#[1, 1, 1]のイメージ、逆元？格納テーブル
    #print(invs)　　⇒　[1, 1, 1]のイメージ、逆元格納テーブル
    invs[n] = inv
    for m in range(n, 1, -1):#n*(n-1)*(n-2)*...と上から掛けている
        inv = inv * m % MOD#なぜ、下から掛けない？
        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)
 
    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)))
# Original solution
'''
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))

# Optimized solution
#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)))
# Original solution
MOD = 10 ** 9 + 7


def power_expo(x, y):
    """Returns x^y.

    <https://qiita.com/Yaruki00/items/fd1fc269ff7fe40d09a6>

    結局, 組み込み関数の `pow()` のほうが速そう. 第3引数でmodもできる.
    """
    if y == 0:
        return 1
    elif y % 2 == 0:
        return power_expo(x, y // 2) ** 2 % MOD
    else:
        return power_expo(x, y // 2) ** 2 * x % MOD


def main():
    x, y = [int(x) for x in input().split()]
    if (x + y) % 3 != 0:
        return 0
    summ = (x + y) // 3     # d + r
    diff = x - y  # d - r
    if summ % 2 != diff % 2:
        return 0
    d = (summ + diff) // 2  # Down
    r = (summ - diff) // 2  # Right
    if d < 0 or r < 0:
        return 0
    chosen = min(d, r)

    patterns = 1

    for i, j in zip(list(range(summ - chosen + 1, summ + 1)), list(range(1, summ + 1))):
        patterns = patterns % MOD * i % MOD * pow(j, MOD - 2, MOD) % MOD

    return patterns


if __name__ == '__main__':
    print((main()))

# やはり難しい，再び解説。割り算のときは mod 10^9+7 が厄介。
# とりあえず，割る方は 10^9+5 乗して掛ければいいらしい。


# Optimized solution
MOD = 10 ** 9 + 7


def power_expo(x, y):
    """Returns x^y.

    <https://qiita.com/Yaruki00/items/fd1fc269ff7fe40d09a6>

    結局, 組み込み関数の `pow()` のほうが速そう. 第3引数でmodもできる.
    """
    if y == 0:
        return 1
    elif y % 2 == 0:
        return power_expo(x, y // 2) ** 2 % MOD
    else:
        return power_expo(x, y // 2) ** 2 * x % MOD


def combinations_mod(n, r, mod=1000000007):
    """Returns nCr in mod."""
    combs = 1
    for i, j in zip(list(range(n - r + 1, n + 1)), list(range(1, r + 1))):
        combs = combs % mod * i % mod * pow(j, mod - 2, mod) % mod
    return combs


def main():
    x, y = [int(x) for x in input().split()]
    if (x + y) % 3 != 0:
        return 0
    summ = (x + y) // 3     # d + r
    diff = x - y  # d - r
    if summ % 2 != diff % 2:
        return 0
    d = (summ + diff) // 2  # Down
    r = (summ - diff) // 2  # Right
    if d < 0 or r < 0:
        return 0
    chosen = min(d, r)

    patterns = combinations_mod(summ, chosen)

    return patterns


if __name__ == '__main__':
    print((main()))

# やはり難しい，再び解説。割り算のときは mod 10^9+7 が厄介。
# とりあえず，割る方は 10^9+5 乗して掛ければいいらしい。
# でかい累乗, pow() なら間に合うな. Python3 1310 ms; Pypy3 457 ms.
# Original solution
import sys
mod=10**9+7
x,y=list(map(int,input().split()))

a=(-x+2*y)//3
b=(2*x-y)//3

if a<0 or b<0:
  print((0))
  sys.exit()
  
f=[1]
for i in range(1,a+b+1):
    f.append(f[-1]*i%mod)

if a+2*b==x and 2*a+b==y:
    print((f[a+b]*pow(f[a]*f[b],mod-2,mod)%mod))
else:
    print((0))

# Optimized solution
import sys
mod=10**9+7
x,y=list(map(int,input().split()))

a=(-x+2*y)//3
b=(2*x-y)//3

if a<0 or b<0:
  print((0))
  sys.exit()
  
f=[1]
for i in range(1,a+b+1):
    f.append(f[-1]*i%mod)

if a+2*b==x and 2*a+b==y:
    print((f[a+b]*pow(f[a],mod-2,mod)*pow(f[b],mod-2,mod)%mod))
else:
    print((0))
# Original solution
X,Y = list(map(int,input().split()))

if (X+Y)%3 != 0 or X > 2*Y or Y > 2*X:
    print((0))
else:
    ab = (X+Y)//3
    a = X - ab
    b = ab - a
    mod = 10**9+7
    def cmb(n, r, mod):
        if ( r<0 or r>n ):
            return 0
        r = min(r, n-r)
        return g1[n] * g2[r] * g2[n-r] % mod

    mod = 10**9+7 #出力の制限
    N = 10**6+1
    g1 = [1, 1] # 元テーブル
    g2 = [1, 1] #逆元テーブル
    inverse = [0, 1] #逆元テーブル計算用テーブル

    for i in range( 2, N + 1 ):
        g1.append( ( g1[-1] * i ) % mod )
        inverse.append( ( -inverse[mod % i] * (mod//i) ) % mod )
        g2.append( (g2[-1] * inverse[-1]) % mod )

    ans = cmb(ab,b,mod)
    print(ans)

# Optimized solution
X,Y = list(map(int,input().split()))
def comb(n,k,p):
  """power_funcを用いて(nCk) mod p を求める"""
  from math import factorial
  if n<0 or k<0 or n<k: return 0
  if n==0 or k==0: return 1
  a = 1
  b = 1
  c = 1
  for i in range(1,n+1):
    a = (a*i)%p
  for i in range(1,k+1):
    b = (b*i)%p
  for i in range(1,n-k+1):
    c = (c*i)%p
  return (a*power_func(b,p-2,p)*power_func(c,p-2,p))%p
def power_func(a,b,p):
  """a^b mod p を求める"""
  if b==0: return 1
  if b%2==0:
    d=power_func(a,b//2,p)
    return d*d %p
  if b%2==1:
    return (a*power_func(a,b-1,p ))%p
if (X+Y)%3 != 0 or X > 2*Y or Y > 2*X:
    print((0))
else:
    ab = (X+Y)//3
    a = X - ab
    b = ab - a
    mod = 10**9+7
    ans = comb(ab,min(a,b),mod)
    print(ans)
# Original solution
X, Y = list(map(int, input().split()))
MOD = 10 ** 9 + 7

def modpow(a, n):
    ret = 1
    while n > 0:
        if n & 1:
            ret = ret * a % MOD
        a = a * a % MOD
        n >>= 1
    return ret

def modinv(a):
    return modpow(a, MOD - 2)

def modfac(x):
    ret = 1
    for i in range(2, x + 1):
        ret *= i
        ret %= MOD
    return ret

ans = 0
if (X + Y) % 3 == 0:
    a = (2 * X - Y) // 3
    b = (2 * Y - X) // 3
    if a >= 0 and b >= 0:
        n = a + b
        r = a
        ans = modfac(n)
        ans *= modinv(modfac(n - r) * modfac(r))
        ans %= MOD
print(ans)

# Optimized solution
X, Y = list(map(int, input().split()))
MOD = 10 ** 9 + 7

def modpow(x, n):
    ret = 1
    while n > 0:
        if n & 1:
            ret = ret * x % MOD
        x = x * x % MOD
        n >>= 1
    return ret

def modinv(x):
    return modpow(x, MOD - 2)

def modf(x):
    ret = 1
    for i in range(2, x + 1):
        ret *= i
        ret %= MOD
    return ret

ans = 0
if (X + Y) % 3 == 0:
    m = (2 * X - Y) // 3
    n = (2 * Y - X) // 3
    if m >= 0 and n >= 0:
        ans = modf(m + n) * modinv(modf(n) * modf(m))
        ans %= MOD
print(ans)
# Original solution
def solve():
    mod = 10 ** 9 + 7

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

    sum_ = x + y

    q, r = divmod(sum_, 3)
    if r != 0:
        return 0

    a = (x * 2 - y) // 3

    b = (y * 2 - x) // 3

    if a < 0 or b < 0:
        return 0

    def cmb(n, r):
        return (fact[n] * finv_t[r] * finv_t[n - r]) % mod

    fact = [1, 1]
    inv_t = [0, 1]
    finv_t = [1, 1]
    for i in range(2, q + 1):
        fact.append((fact[-1] * i) % mod)
        inv_t.append((-inv_t[mod % i] * (mod // i)) % mod)
        finv_t.append((finv_t[-1] * inv_t[-1]) % mod)

    return cmb(q, a)


print((solve()))


# Optimized solution
def main():
    mod = 10 ** 9 + 7

    def choose(n, a, mod=mod):
        x, y = 1, 1
        for i in range(a):
            x = x * (n - i) % mod
            y = y * (i + 1) % mod
        return x * pow(y, mod - 2, mod) % mod

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

    q, r = divmod(x + y, 3)
    if r != 0:
        print((0))
        return

    # b:=(+2,+1)
    d = x * 2 - y
    if d < 0 or d % 3 != 0:
        print((0))
        return

    b = d // 3
    if q < b:
        print((0))
        return
    res = choose(q, min(b, q - b), mod)
    print(res)


if __name__ == '__main__':
    main()
# Original solution
X,Y=list(map(int,input().split()))

mod=10**9+7
def nCr(n, r, mod):
    r = min(r, n-r)
    numer = denom = 1
    for i in range(1, r+1):
        numer = numer * (n+1-i) % mod
        denom = denom * i % mod
    return numer * pow(denom, mod-2, mod) % mod

if (X+Y)%3 != 0:
      print((0))
      exit()
 
n,x,y=0,X,Y
while x != y*2:
      x-=1
      y-=2
      n+=1

m=((X+Y)//3)-n

if n<0 or m<0:
    print((0))
    exit()

ans = nCr(n+m,n,mod)
print(ans)


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

mod=10**9+7
def nCr(n, r, mod):
    r = min(r, n-r)
    numer = denom = 1
    for i in range(1, r+1):
        numer = numer * (n+1-i) % mod
        denom = denom * i % mod
    return numer * pow(denom, mod-2, mod) % mod

if (X+Y)%3 != 0:
      print((0))
      exit()
 
n=((2*X)-Y)//3

m=((X+Y)//3)-n

if n<0 or m<0:
    print((0))
    exit()

ans = nCr(n+m,n,mod)
print(ans)
# Original solution
class Solution:
    def solve(self, x: int, y: int) -> int:

        if (2*x - y) % 3 != 0 or (-x + 2*y) % 3 != 0:
            return 0

        m = (2*x - y) // 3
        n = (-x + 2*y) // 3

        if m < 0 or n < 0:
            return 0

        # calculate {m+n}C{n}
        def egcd(a, b):
            if a == 0:
                return b, 0, 1
            else:
                g, y, x = egcd(b % a, a)
                return g, x - (b // a) * y, y

        def modinv(a, m):
            g, x, y = egcd(a, m)
            if g != 1:
                raise Exception('modular inverse does not exist')
            else:
                return x % m

        def convination(n: int, r: int, mod: int = 10**9+7) -> int:
            r = min(r, n-r)
            res = 1
            for i in range(r):
                res = res * (n-i) * modinv(i+1, mod) % mod
            return res

        return convination(n+m, m)


if __name__ == '__main__':

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

    # solve
    solution = Solution()
    print((solution.solve(x, y)))


# Optimized solution
class MathUtil:
    # calculate {m+n}C{n}
    def egcd(self, a: int, b: int):
        if a == 0:
            return b, 0, 1
        else:
            g, y, x = self.egcd(b % a, a)
            return g, x - (b // a) * y, y

    def modinv(self, a: int, m: int):
        g, x, y = self.egcd(a, m)
        if g != 1:
            raise Exception('modular inverse does not exist')
        else:
            return x % m

    def combination(self, n: int, r: int, mod: int = 10**9+7) -> int:
        r = min(r, n-r)
        res = 1
        for i in range(r):
            res = res * (n-i) * self.modinv(i+1, mod) % mod
        return res


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


m = - x + 2*y
n = 2*x - y

if m % 3 != 0 or n % 3 != 0 or m < 0 or n < 0:
    print((0))
else:
    m //= 3
    n //= 3

    print((MathUtil().combination(m+n, n)))
# Original solution
# nCrの左項には nn しか来ない場合、1!～(n-1)!は保持しなくてよいバージョン 
def prepare(n, MOD):
  # n! の計算
  f = 1
  for m in range(1, n+1):
    f *= m
    f %= MOD
  fn = f
  # n!^-1 の計算
  inv = pow(f, MOD-2, MOD)
  # n!^-1 - 1!^-1 の計算
  invs = [1]*(n+1)
  invs[n] = inv
  for m in range(n, 1, -1):
    inv *= m
    inv %= MOD
    invs[m-1] = inv
    
  return fn, invs

MOD = 10**9+7
x, y = list(map(int, input().split()))

d, m = divmod(x+y, 3)
if m != 0 or x/y > 2 or y/x > 2:
  print((0))
  exit()
c = abs(d-x)
f, invs = prepare(d, MOD)
ans = f * invs[c] * invs[d-c] % MOD
print(ans)

# Optimized solution
# nCr mod m
# rがn/2に近いと非常に重くなる
def combination(n, r, mod=10**9+7):
    n1, r = n+1, min(r, n-r)
    numer = denom = 1
    for i in range(1, r+1):
        numer = numer * (n1-i) % mod
        denom = denom * i % mod
    return numer * pow(denom, mod-2, mod) % mod
  
X, Y = list(map(int, input().split()))
if (X+Y) % 3 != 0 or not (X <= 2*Y and Y <= 2*X):
    print((0))
    exit()

n = (X+Y) // 3
r = Y - n
#print(n, r)
print((combination(n, r)))
# Original solution
# 法Pの下での組み合わせ数 nCk を求める
# MAX: nの最大値

P = (10**9)+7

fac=[]
inv=[]
finv=[]

# 拡張ユークリッドアルゴリズム
# (d, x, y): d=ax+by を満たすd, x, yを求める
# aとbが互いに素な整数であればgcd(a,b)=d=1, ax=1 (mod b)
# xは法bの元でaの乗法逆元a^-1になる
def exEuclid(a, b):
    if (b==0):
        return (a, 1, 0)
    else:
        (dd, xx, yy) = exEuclid(b, a % b)
        return (dd, yy, xx - (a//b)*yy)

def COMinit(MAX):
    global fac, inv, finv
    fac=[1 for _ in range(MAX)]
    inv=[1 for _ in range(MAX)]
    finv=[1 for _ in range(MAX)]
    #print('len(fac): {}'.format(len(fac)))
    #print(MAX)
    for i in range(2,MAX):
        #print(i)
        fac[i] = fac[i-1]*i % P
        (d, x, y) = exEuclid(i, P)
        inv[i] = x
        finv[i] = finv[i-1]*inv[i] % P

def COM(n, k):
    if(n<k):
        return 0
    elif ( (n<0)or(k<0)):
        return 0
    else:
        return fac[n]*(finv[n-k]*finv[k] % P) % P

####

#print('x, y:')
x, y = list(map(int,input().split()))
MAX = (x+y)//3 +1  # (X+Y)/3より大きい整数 1 <= X, Y <= 10**6
COMinit(MAX)

if ((x+y)%3 != 0):
    print((0))
    exit()
else:
    n1 = (-x+2*y)//3
    n2 = (2*x -y)//3
    if (n1<0):
        print((0))
        exit()
    elif(n2<0):
        print((0))
        exit()
    else:
        npath = COM(n1+n2, n1)
        print(npath)



# Optimized solution
# 拡張ユークリッドアルゴリズム
# (d, x, y): d=ax+by を満たすd, x, yを求める
# aとbが互いに素な整数であればgcd(a,b)=d=1, ax=1 (mod b)
# xは法bの元でaの乗法逆元a^-1になる
def exEuclid(a, b):
    if (b==0):
        return (a, 1, 0)
    else:
        (dd, xx, yy) = exEuclid(b, a % b)
        return (dd, yy, xx - (a//b)*yy)

def mycomb(n, k, p):
    k = min(n-k,k)
    fact=1
    finv=1
    for i in range(k):
        fact=fact*(n-i) % p
        finv=finv*(i+1) % p
    (d, x, y) = exEuclid(finv, p)
    return fact*x % p

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

if ((x+y)%3 != 0):
    print((0))
    exit()
else:
    n1 = (-x+2*y)//3
    n2 = (2*x -y)//3
    if( (n1<0) or (n2<0) ):
        print((0))
        exit()
    npath = mycomb(n1+n2, n2, 10**9+7)
    print(npath)
# Original solution
MOD = 10 ** 9 + 7

#互いに素なa,bについて、a*x+b*y=1の一つの解
def extgcd(a,b):
    r = [1,0,a]
    w = [0,1,b]
    while w[2]!=1:
        q = r[2]//w[2]
        r2 = w
        w2 = [r[0]-q*w[0],r[1]-q*w[1],r[2]-q*w[2]]
        r = r2
        w = w2
    #[x,y]
    return [w[0],w[1]]

# aの逆元(mod m)を求める。(aとmは互いに素であることが前提)
def mod_inv(a,m):
    x = extgcd(a,m)[0]
    return (m+x%m)%m

X, Y = list(map(int, input().split()))
if (X + Y) % 3 != 0:
    print((0))
    exit()
time = (X+Y) // 3
diff = X - Y
if abs(diff) > time:
    print((0))
    exit()
x_time = (time+diff) // 2
res = 1
for i in range(1,time+1):
    res = res*i%MOD
for i in range(1,x_time+1):
    res = res*mod_inv(i,MOD)%MOD
for i in range(1,time-x_time+1):
    res = res*mod_inv(i, MOD)%MOD
print(res)
#print(mod_combination(time, x_time, MOD))


# Optimized solution
def cmb(n, k, mod, fac, ifac):
    # nCkを計算する
    k = min(k, n-k)
    return fac[n] * ifac[k] * ifac[n-k] % mod

def make_tables(mod, n):
    # 階乗テーブル、逆元の階乗テーブルを作成する
    fac = [1, 1] # 階乗テーブル
    ifac = [1, 1] # 逆元の階乗テーブル
    inverse = [0, 1] # 逆元テーブル 0の階乗は1

    for i in range(2, n+1):
        fac.append((fac[-1] * i) % mod)
        inverse.append((-inverse[mod % i] * (mod//i)) % mod)
        ifac.append((ifac[-1] * inverse[-1]) % mod)
    return fac, ifac

X, Y = list(map(int, input().split()))
if X > Y:
    X, Y = Y, X
dist = X + Y
if dist % 3 != 0:
    print((0))
    exit()

total = int((X+Y) / 3)
n = X - total
if Y > 2*X:
    print((0))
else:
    MOD = 10**9 + 7
    fac, ifac = make_tables(MOD, total)
    answer = cmb(total, n, MOD, fac, ifac)
    print(answer)

"""
p = (p/a)×a + (p %a)
この両辺の mod p をとると、
(p/a)×a + (p%a) ≡ 0
⇔(p/a) + (p%a)×a−1 ≡ 0　(両辺に a−1 をかける)

⇔(p%a) × a−1 ≡ −(p/a)
⇔a−1 ≡ −(((p%a)^−1) × (p/a))
"""
# Original solution
def cmb(n, k, mod, fac, ifac):
    # nCkを計算する
    k = min(k, n-k)
    return fac[n] * ifac[k] * ifac[n-k] % mod

def make_tables(mod, n):
    # 階乗テーブル、逆元の階乗テーブルを作成する
    fac = [1, 1] # 階乗テーブル
    ifac = [1, 1] # 逆元の階乗テーブル
    inverse = [0, 1] # 逆元テーブル 0の階乗は1

    for i in range(2, n+1):
        fac.append((fac[-1] * i) % mod)
        inverse.append((-inverse[mod % i] * (mod//i)) % mod)
        ifac.append((ifac[-1] * inverse[-1]) % mod)
    return fac, ifac

X, Y = list(map(int, input().split()))
if X > Y:
    X, Y = Y, X
dist = X + Y
if dist % 3 != 0:
    print((0))
    exit()

total = int((X+Y) / 3)
n = X - total
if Y > 2*X:
    print((0))
else:
    MOD = 10**9 + 7
    fac, ifac = make_tables(MOD, total)
    answer = cmb(total, n, MOD, fac, ifac)
    print(answer)

"""
p = (p/a)×a + (p %a)
この両辺の mod p をとると、
(p/a)×a + (p%a) ≡ 0
⇔(p/a) + (p%a)×a−1 ≡ 0　(両辺に a−1 をかける)

⇔(p%a) × a−1 ≡ −(p/a)
⇔a−1 ≡ −(((p%a)^−1) × (p/a))
"""

# Optimized solution
import sys

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

def cmb(n, k, mod, fac, ifac):
    # nCkを計算する
    k = min(k, n-k)
    return fac[n] * ifac[k] * ifac[n-k] % mod

def make_tables(mod, n):
    # 階乗テーブル、逆元の階乗テーブルを作成する
    fac = [1, 1] # 階乗テーブル
    ifac = [1, 1] # 逆元の階乗テーブル
    inverse = [0, 1] # 逆元テーブル 0の階乗は1 0の逆元は0

    for i in range(2, n+1):
        fac.append((fac[-1] * i) % mod)
        inverse.append((-inverse[mod % i] * (mod//i)) % mod)
        ifac.append((ifac[-1] * inverse[-1]) % mod)
    return fac, ifac

X, Y = lr()
MOD = 10 ** 9 + 7
if (X+Y)%3 != 0 or X > 2 * Y or Y > 2 * X:
    print((0))
    exit()
if X < Y:
    X, Y = Y, X
# Xが大きい
total_time = (X+Y)//3
x_time = (X - Y + total_time) // 2
# total_time C i_time
fac, ifac = make_tables(MOD, total_time)
answer = fac[total_time] * ifac[x_time] * ifac[total_time - x_time] % MOD
print(answer)
# 44