Problem:
 Score : 400 points    Problem Statement There is a knight - the chess piece - at the origin (0, 0) of a two-dimensional grid.  When the knight is at the square (i, j) , it can be moved to either (i+1,j+2) or (i+2, j+1) .  In how many ways can the knight reach the square (X, Y) ?  Find the number of ways modulo 10^9 + 7 .      Constraints  1 \leq X \leq 10^6  1 \leq Y \leq 10^6  All values in input are integers.         Input Input is given from Standard Input in the following format:  X  Y       Output Print the number of ways for the knight to reach (X, Y) from (0, 0) , modulo 10^9 + 7 .        Sample Input 1 3 3      Sample Output 1 2  There are two ways: (0,0) \to (1,2) \to (3,3) and (0,0) \to (2,1) \to (3,3) .       Sample Input 2 2 2      Sample Output 2 0  The knight cannot reach (2,2) .       Sample Input 3 999999 999999      Sample Output 3 151840682  Print the number of ways modulo 10^9 + 7 .

Solution (Python):
X, Y = (int(i) for i in input().split())

def power(a, b):
	if b == 0:
		return 1
	elif b == 1:
		return a % 1000000007
	elif b % 2 == 0:
		return (power(a, b//2) ** 2) % 1000000007
	else:
		return (power(a, b//2) ** 2 * a) % 1000000007

def divide(a, b):
	return (a * power(b, 1000000005)) % 1000000007



fac_lim = 1000000
fac = [None]*(fac_lim+1)
fac[0] = 1
for i in range(fac_lim):
    fac[i+1] = fac[i] * (i+1)
    fac[i+1] = fac[i + 1] % 1000000007

fac_inv = [None]*(fac_lim+1)
fac_inv[fac_lim] = power(fac[fac_lim], 1000000005)
for i in range(fac_lim, 0, -1):
    fac_inv[i-1] = (fac_inv[i] * i)  % 1000000007

def conv(a, b):
    return (fac[a] * fac_inv[a-b] * fac_inv[b]) % 1000000007


MOD = 10**9 + 7
if (X+Y)%3 != 0:
    ans = 0
else:
    N = (X+Y)//3
    M = X - Y
    if (N+M)%2 !=0:
        ans = 0
    else:
        a = (N+M)//2
        if 0 <= a <= N:
            ans = conv(N, a)
        else:
            ans = 0
print(ans%MOD)

Solution (Python):
X,Y = list(map(int,input().split()))
mod = 10**9+7
fac = [1, 1]
finv = [1, 1]
inv = [0, 1]

Xd = (2*X-Y)/3
Yd = (-X+2*Y)/3

def init(n):
    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)

def com(n, k, mod):
    if n < 0 or k < 0 or n < k:
        return 0
    return fac[n] * (finv[k] * finv[n - k] % mod) % mod

if Xd % 1 == 0 and Yd % 1 == 0:
    init(int(Xd+Yd))
    print(com(int(Xd+Yd), int(Yd), mod)) 
else:
    print('0')

Solution (Python):
def main():
    import sys
    input = sys.stdin.readline

    x,y = map(int,input().split())
    a_old = 2 * y - x
    b_old = 2 * x - y

    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

    if (a_old % 3 == 0) and (b_old % 3 == 0) and (a_old >= 0) and (b_old >= 0):
        a_new = int(a_old // 3)
        b_new = int(b_old // 3)
        n = a_new + b_new
        r = cmb(n,a_new)
        print(int(r % (10**9 + 7)))
    else:
        print(0)

if __name__ == "__main__":
    main()

Solution (Python):
X, Y = map(int, input().split())
mod = 10 ** 9 + 7



def comb_mod(n, r, mod):
    num = 1
    den = 1
    for i in range(r):
        num = (num * (n - i)) % mod
        den = (den * (i + 1)) % mod
    den_r = pow(den, mod - 2, mod)
    return (num * den_r) % mod



n = (2 * Y - X) // 3
m = (2 * X - Y) // 3



if (X + Y) % 3 != 0 or n < 0 or m < 0:
    print(0)
else:
    print(comb_mod(n + m, n, mod))

Solution (Python):

import sys
MOD = 1000000007  


def comb(n, k):
    k = min(n-k,k)
    ans = 1
    for i in range(1, k + 1):
        ans *= (n + 1 - i) * pow(i,MOD-2,MOD)
        ans %= MOD
    return ans

def solve(X: int, Y: int):
    if (X+Y)%3 != 0 or Y*2-X < 0 or X*2-Y < 0:
        print(0)
        return

    
    a = (Y*2-X)//3
    b = (X*2-Y)//3
    print(comb(a+b,a))
    return

def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    X = int(next(tokens))  
    Y = int(next(tokens))  
    solve(X, Y)

if __name__ == '__main__':
    main()

Solution (Python):
from functools import reduce
mod = 10**9+7
def mul(a,b):
    return a*b % mod
def cmb(n,r,mod):
    if r == 0:
        return 1
    if r == 1:
        return n % mod 
    above = reduce(mul,range(n-r+1,n+1)) 
    below = reduce(mul,range(1,r+1)) 
    ans = above*pow(below,mod-2,mod) % mod
    if ans < 0:
        ans += mod
    return ans
x,y = map(int,input().split())
if 2*x-y < 0 or 2*y-x<0 or (2*x-y) % 3 != 0:
    print(0)
    exit()
a = (2*x-y)//3
b = (2*y-x)//3
print(cmb(a+b,min(a,b),mod))

Solution (Python):
X,Y=map(int,input().split())
mod=10**9+7
"""2a+b=X 2b+a=Yを満たすabの並び替え"""


if (X+Y)%3!=0:
    print("0")
else:
    a=min(((X+Y)//3+(X-Y))//2,((X+Y)//3-(X-Y))//2)
    b=max(((X+Y)//3+(X-Y))//2,((X+Y)//3-(X-Y))//2)
    
    c=1
    d=1
    if a>0 and b>=0:
        for i in range(a):
            c*=(a+b-i)
            c=c%mod
            d*=(i+1)
            d=d%mod
        print((c*pow(d,mod-2,mod))%mod)
    elif a==0 and b>0:
        print("1")
    else:
        print("0")

Solution (Python):
X,Y = map(int, input().split())

mod=10 ** 9 + 7
def binomial(n,k):
    x=1
    y=1
    for i in range(k):
        x=x*(n-i)%mod
        y=y*(i+1)%mod
    return x*pow(y,mod-2,mod)%mod

if (2*X-Y)%3==0 and  (2*Y-X)%3==0:
    a=(2*X-Y)//3
    b=(2*Y-X)//3
    if a<0 or b<0:
        print(0)        
    else:
        print(binomial(a+b,a)%mod)
else:
    print(0)

Solution (Python):
import sys
from math import *
from collections import deque, Counter, defaultdict
from fractions import gcd
input = lambda: sys.stdin.readline().rstrip()

def eprint(s):
    sys.stderr.write('DEBUG: {}'.format(s))
    return

""" 
参考:http://drken1215.hatenablog.com/entry/2018/06/08/210000
maximとmodを適宜設定。
あ入力忘れを考慮してあえて入力例通らないようにしておいたで。

combを使う前にcominit()を使う

"""
maxim = 10**6 + 10
mod = 10**9+7
fac = [None] * maxim
finv = [None] * maxim
inv = [None] * maxim

def cominit():
    fac[0], fac[1] = 1, 1
    finv[0], finv[1] = 1, 1
    inv[1] = 1

    for i in range(2, maxim):
        fac[i] = fac[i-1] * i % mod
        inv[i] = mod - inv[mod % i] * (mod // i) % mod
        finv[i] = finv[i-1] * inv[i] % mod

def com(n, k):
    if (n < k):
        return 0
    if (n < 0 or k < 0):
        return 0

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


def main():
    x,y = map(int, input().split())
    if (x+y) % 3 != 0 or x/2 > y or y > 2*x:
        print(0)
        return

    
    

    
    
    
    k = (x+y) // 3
    
    
    

    cominit()
    m = (2*y-x)//3
    n = m+x-y
    
    print(com(m+n,n))

    return

if __name__ == '__main__':
    main()

Solution (Python):
x, y = map(int, input().split())
mod = 10**9+7 
def check(x, y):
  if (2*y-x)/3 < 0 or (2*x -y)/3 < 0:
    return False
  if (x+y)%3 != 0:
    return False
  return True

def modPow(a, n, mod):
  if n == 1:
    return a % mod
  if n%2 == 1:
    return (a * modPow(a, n - 1, mod)) % mod
  t = modPow(a, n / 2, mod)
  return (t * t) % mod

def comb(n, r, mod):
    r = min(r, n-r)
    x, y  = 1, 1
    for i in range(1, r+1):
      y =  y* i % mod
      x =  x* (n+1-i) % mod
    return x * modPow(y, mod-2, mod) % mod
  
if check(x, y):
  print(comb((2*y-x)//3+(2*x -y)//3, (2*y-x)//3, mod))
else:
  print(0)

Solution (Python):
x, y = map(int, input().split())
mod = 10**9+7 
def check(x, y):
  if (2*y-x)/3 < 0 or (2*x -y)/3 < 0:
    return False
  if (x+y)%3 != 0:
    return False
  return True

def comb(n, r, mod):
    r = min(r, n-r)
    x, y  = 1, 1
    for i in range(1, r+1):
      y =  y* i % mod
      x =  x* (n+1-i) % mod
    return x * pow(y, mod-2, mod) % mod
  
if check(x, y):
  print(comb((2*y-x)//3+(2*x -y)//3, (2*y-x)//3, mod))
else:
  print(0)

Solution (Python):
def find_power(n):
    
    powlist=[0]*(n+1)
    powlist[0]=1
    powlist[1]=1
    for i in range(2,n+1):
        powlist[i]=powlist[i-1]*i%(10**9+7)
    return powlist
def find_inv_power(n):
    
    powlist=find_power(n)
    check=powlist[-1]
    first=1
    uselist=[0]*(n+1)
    secondlist=[0]*30
    secondlist[0]=check
    secondlist[1]=check**2
    for i in range(28):
        secondlist[i+2]=(secondlist[i+1]**2)%(10**9+7)
    a=format(10**9+5,"b")
    for j in range(30):
        if a[29-j]=="1":
            first=(first*secondlist[j])%(10**9+7)
    uselist[n]=first
    for i in range(n,0,-1):
        uselist[i-1]=(uselist[i]*i)%(10**9+7)
    return uselist
def combi(a,b,n,r,mod):
    if n<r:
        return 0
    elif n>=r:
        return (a[n]*b[r]*b[n-r])%(mod)
          
x,y=map(int,input().split())
power=find_power(666670)
invpower=find_inv_power(666670)
if (2*x-y)%3==0 and (2*y-x)%3==0:
    if (2*x-y)>=0 and (2*y-x)>=0:
        a=(2*y-x)//3
        b=(2*x-y)//3
        print(combi(power,invpower,a+b,b,10**9+7))
    else:
        print(0)
else:
    print(0)

Solution (Python):
mod=10**9+7

def pow_cal(x,n,mod):
    if n==0:
        return 1
    elif n==1:
        return x%mod
    elif n>=2:
        if n%2==0:
            return (pow_cal(x,n//2,mod)**2)%mod
        else:
            return (x*pow_cal(x,n//2,mod)**2)%mod

def find_power(n,mod):
    
    powlist=[0]*(n+1)
    powlist[0]=1
    powlist[1]=1
    for i in range(2,n+1):
        powlist[i]=powlist[i-1]*i%(mod)
    return powlist
 
def find_inv_power(n,mod):
    
    c=1
    uselist=[0 for i in range(n+1)]
    for i in range(1,n+1):
        c*=i
        c%=mod
    first=pow_cal(c,mod-2,mod)
    uselist[n]=first
    for i in range(n,0,-1):
        uselist[i-1]=(uselist[i]*i)%(mod)
    return uselist
    
A=find_power(10**6,mod)
B=find_inv_power(10**6,mod)

def combi(n,r,mod):
    if n<r:
        return 0
    elif n>=r:
        return (A[n]*B[r]*B[n-r])%(mod)
x,y=map(int,input().split())
if (x+y)%3!=0:
    print(0)
else:
    J=(2*y-x)//3
    K=(2*x-y)//3
    if J>=0 and K>=0:
        print(combi(J+K,J,mod))
    else:
        print(0)

Solution (Python):
def JOI14_B():
    N = I()
    A = [I()for _ in range(N)]
    A.extend(A)
    dp = [[0]*(N*2+1) for _ in range(N*2+1)]

    for j in range(N):
        for i in range(N*2-j):
            if (N-j)%2==1:
                dp[i][i+j] = max(dp[i+1][i+j]+A[i],dp[i][i+j-1]+A[i+j])
            else:
                if A[i]>A[i+j]:
                    dp[i][i+j] = dp[i+1][i+j]
                else:
                    dp[i][i+j] = dp[i][i+j-1]
    ans = 0
    for i in range(N):
        ans = max(ans,dp[i][i+N-1])
    print(ans)
    
    return

def square869120Contest1_G():
    def held_karp(dists,TL):
        
        """
        Implementation of Held-Karp, an algorithm that solves the Traveling
        Salesman Problem using dynamic programming with memoization.
        Parameters:
            dists: distance matrix
        Returns:
            A tuple, (cost, path).
        """
        n = len(dists)

        
        
        
        C = {}
        dp = defaultdict(int)

        
        for k in range(1, n):
            C[(1 << k, k)] = (dists[0][k], 0)
            dp[(1 << k, k)] = 1

        
        
        for subset_size in range(2, n):
            for subset in itertools.combinations(range(1, n), subset_size):
                
                bits = 0
                for bit in subset:
                    bits |= 1 << bit
                shortest_length = inf
                
                for k in subset:
                    prev = bits & ~(1 << k)

                    res = []
                    for m in subset:
                        if not (prev, m) in C:
                            continue
                        if m == 0 or m == k:
                            continue
                        if C[(prev, m)][0] + dists[m][k]>TL[m][k]:
                            continue
                        res.append((C[(prev, m)][0] + dists[m][k], m))
                        if shortest_length>C[(prev, m)][0] + dists[m][k]:
                            shortest_length = C[(prev, m)][0] + dists[m][k]
                    if not res:
                        continue
                    C[(bits, k)] = min(res)
                    for d,m in res:
                        if shortest_length!=d:
                            continue
                        dp[(bits, k)] += dp[(prev,m)]

        
        bits = (2 ** n - 1) - 1

        
        res = []
        shortest_length = inf
        for k in range(1, n):
            if not (bits, k) in C:
                continue
            if C[(bits, k)][0] + dists[k][0] > TL[k][0]:
                continue
            res.append((C[(bits, k)][0] + dists[k][0], k))
            if shortest_length > C[(bits, k)][0] + dists[k][0]:
                shortest_length = C[(bits, k)][0] + dists[k][0]
        if not res:
            return False
        opt, parent = min(res)
        way = 0
        for d, k in res:
            if not (bits, k) in C:
                continue
            if C[(bits, k)][0] + dists[k][0] > TL[k][0]:
                continue
            if shortest_length < d:
                continue
            way += dp[(bits,k)]

        
        path = []
        for i in range(n - 1):
            path.append(parent)
            new_bits = bits & ~(1 << parent)
            _, parent = C[(bits, parent)]
            bits = new_bits

        
        path.append(0)

        return shortest_length, list(reversed(path)), way

    N, M = LI()
    dist = [[inf]*N for _ in range(N)]
    TL = [[0]*N for _ in range(N)]
    for _ in range(M):
        s, t, d, time = LI()
        s -= 1; t -= 1
        dist[s][t] = dist[t][s] = d
        TL[s][t] = TL[t][s] = time
    ans = held_karp(dist,TL)
    if (not ans) or ans[2]==0:
        print("IMPOSSIBLE")
        return
    print(ans[0],ans[2])
    return

def JOI13_D():
    def solve(yday,leader,next):
        a = [0]*3
        for i in range(3):
            if next&(1<<i)==(1<<i):
                a[i] = 1
        rep = 0
        if a[leader]==0:
            return rep
        for i in range(3):
            if yday&(1<<i)==(1<<i):
                if a[i]==1:
                    rep = 1
        return rep
    N = I()
    S = SI()
    member = {"J":0,"O":1,"I":2}
    dp = [[0]*8 for _ in range(N+1)]
    dp[0][1] = 1
    for i in range(N):
        leader = member[S[i]]
        for j in range(8):
            for k in range(8):
                dp[i+1][j] += (dp[i][k]*solve(k,leader,j))
    ans = sum(dp[-1])%10007
    
    print(ans)
    return

def JOI16_D():
    N, M = LI()
    A = [(I()-1)for _ in range(N)]
    imos = [[0] * (N + 1) for _ in range(M)]
    for i in range(M):
        for j in range(N):
            imos[i][j + 1] += imos[i][j] + (A[j] != i)
    loop = 2**M
    dp = [inf]*loop
    dp[0] = 0
    cnt = Counter(A)
    L = [0]*loop
    
    for i in range(loop):
        for j in range(M):
            if i&(1<<j)==(1<<j):
                continue
            next = i|(1<<j)
            if L[next]==0:
                L[next] = L[i]+cnt[j]
            cur = imos[j][L[next]] - imos[j][L[i]]
            if dp[next]>dp[i] + cur:
                dp[next] = dp[i] + cur
    ans = dp[-1]
    
    print(ans)
    return

def ABC6_D():
    N = I()
    C = [I() for _ in range(N)]
    LIS = [C[0]]
    for i in range(N):
        if C[i] > LIS[-1]:
            LIS.append(C[i])
        else:
            LIS[bisect.bisect_left(LIS, C[i])] = C[i]
    print(N - len(LIS))
    return

def ABC134_E():
    N = I()
    A = [I()for _ in range(N)]
    que = deque()
    que.append(A[0])
    L = 1
    for i in range(1,N):
        cur = bisect.bisect_left(que,A[i])
        
        if cur==0:
            que.appendleft(A[i])
            L += 1
        else:
            que[cur-1] = A[i]

    
    ans = len(que)
    print(ans)

    return

def JOI7_F():
    def dijkstra_2(edge_adj, node, start):
        
        
        dist = [inf] * node
        used = [False] * node
        dist[start] = 0
        while True:
            v = -1
            for i in range(node):
                if not used[i] and (v == -1 or dist[v] > dist[i]):
                    v = i
            if v == -1:
                break
            used[v] = True
            for i in range(node):
                if dist[i] > dist[v] + edge_adj[v][i]:
                    dist[i] = dist[v] + edge_adj[v][i]
        return dist
    N, K = LI()
    V = [[inf]*N for _ in range(N)]
    ans = []
    for _ in range(K):
        A = LI()
        s = A[1]-1
        t = A[2]-1
        if A[0]==1:
            if V[s][t] <= A[3]:
                continue
            V[s][t] = A[3]
            V[t][s] = A[3]
        else:
            dist = dijkstra_2(V,N,s)
            ans.append(dist[t])
    for v in ans:
        if v==inf:
            print(-1)
            continue
        print(v)
    return

def JOI15_E():
    def bfs(n, E, fordfs):
        
        W = [inf] * n
        
        que = deque()
        for e in E:
            e -=1
            W[e] = 0
            que.append(e)
        while que:
            now = que.popleft()
            nowW = W[now]
            for ne in fordfs[now]:
                if W[ne] > nowW + 1:
                    W[ne] = nowW + 1
                    que.append(ne)
        return W

    class Dijkstra(object):
        """
        construct: O(ElogV)
        """

        def __init__(self, edges, start=0):
            """
            :param list of list of list of int edges:
            :param int start=0:
            """
            self.__dist = [inf] * len(edges)
            self.__dist[start] = 0
            self.__calculate(edges, start)

        @property
        def dist(self):
            return self.__dist

        def __calculate(self, edges, start):
            Q = [(0, start)]  
            while (Q):
                dist, v = heapq.heappop(Q)
                if self.dist[v] < dist: continue  
                for u, cost in edges[v]:
                    if self.dist[u] > self.dist[v] + cost:
                        self.__dist[u] = self.dist[v] + cost
                        heapq.heappush(Q, (self.dist[u], u))
    N, M, K, S = LI()
    P, Q = LI()
    C = [I()for _ in range(K)]
    V = [[]for _ in range(N)]
    for _ in range(M):
        s, t = LI()
        s -= 1
        t -= 1
        V[s].append(t)
        V[t].append(s)
    L = bfs(N,C,V)
    
    cost = [[]for _ in range(N)]
    for i in range(N):
        for v in V[i]:
            if L[v]==0:
                continue
            elif L[v]<=S:
                cost[i].append((v,Q))
            else:
                cost[i].append((v,P))
    di = Dijkstra(cost)
    ans = di.dist
    
    if L[-1]<=S:
        print(ans[N-1]-Q)
    else:
        print(ans[N-1]-P)
    return

def JOI13_E():
    def bfs(n, e, fordfs):
        
        W = [inf] * n
        
        W[e] = 0
        que = deque()
        que.append(e)
        while que:
            now = que.popleft()
            nowW = W[now]
            for ne in fordfs[now]:
                if W[ne] == inf:
                    W[ne] = nowW + 1
                    que.append(ne)
        return W

    def dijkstra_2(edge_adj, node, start):
        
        
        dist = [inf] * node
        used = [False] * node
        dist[start] = 0
        while True:
            v = -1
            for i in range(node):
                if not used[i] and (v == -1 or dist[v] > dist[i]):
                    v = i
            if v == -1:
                break
            used[v] = True
            for i in range(node):
                if dist[i] > dist[v] + edge_adj[v][i]:
                    dist[i] = dist[v] + edge_adj[v][i]
        return dist
    N, K = LI()
    C = [[]for _ in range(N)]
    V = [[]for _ in range(N)]
    for i in range(N):
        C[i] = LI()
    for i in range(K):
        a, b = LI()
        a -= 1
        b -= 1
        V[a].append(b)
        V[b].append(a)
    costV = [[inf]*N for _ in range(N)]
    for i in range(N):
        L = bfs(N,i,V)
        c = C[i][0]; l = C[i][1]
        for j in range(N):
            if i==j:
                continue
            if L[j]<=l:
                costV[i][j] = c
    dist = dijkstra_2(costV,N,0)
    ans = dist[N-1]
    
    print(ans)
    return

def ABC12_D():
    def warshall_floyd(n, d):
        
        for k in range(n):
            for i in range(n):
                for j in range(n):
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j])
        return d
    N, M = LI()
    V = [[inf]*N for _ in range(N)]
    for i in range(N):
        V[i][i] = 0
    for _ in range(M):
        a, b, t = LI()
        a -= 1
        b -= 1
        V[a][b] = t
        V[b][a] = t
    L = warshall_floyd(N,V)
    
    ans = inf
    for i in range(N):
        cur = max(L[i])
        ans = min(ans,cur)
    print(ans)
    return

def ABC79_D():
    def warshall_floyd(n, d):
        
        for k in range(n):
            for i in range(n):
                for j in range(n):
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j])
        return d
    H, W = LI()
    C = [LI()for _ in range(10)]
    A = [LI()for _ in range(H)]
    L = warshall_floyd(10,C)
    
    ans = 0
    for a in A:
        for i in a:
            if i>=0:
                ans += L[i][1]
    print(ans)
    return

def JOIgassyuku10_3():
    N, M, K = LI()
    V = [[]for _ in range(N)]
    for _ in range(M):
        a, b, c = LI()
        a -= 1
        b -= 1
        V[a].append((b,c))
        V[b].append((a,c))


    return

def ABC74_D():
    def warshall_floyd(n, d):
        
        for k in range(n):
            for i in range(n):
                for j in range(n):
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j])
        return d
    N = I()
    A = [LI() for _ in range(N)]
    dist = warshall_floyd(N,copy.deepcopy(A))
    shortest_path = 0
    for i in range(N):
        for j in range(N):
            if i==j:
                continue
            if dist[i][j]<A[i][j]:
                print(-1)
                return
            if dist[i][j]>A[i][j]:
                continue
            flag = True
            for k in range(N):
                if i==k or j==k:
                    continue
                judge = (dist[i][k]+dist[k][j])-dist[i][j]
                if judge==0:
                    flag = False
            if flag:
                shortest_path += A[i][j]
    ans = shortest_path//2
    print(ans)
    return

def ABC65_D():
    class Kruskal_UnionFind():
        
        def __init__(self, N):
            self.edges = []
            self.rank = [0] * N
            self.par = [i for i in range(N)]
            self.counter = [1] * N

        def add(self, u, v, d):
            """
            u = from, v = to, d = cost
            """
            self.edges.append([u, v, d])

        def find(self, x):
            if self.par[x] == x:
                return x
            else:
                self.par[x] = self.find(self.par[x])
                return self.par[x]

        def unite(self, x, y):
            x = self.find(x)
            y = self.find(y)
            if x != y:
                z = self.counter[x] + self.counter[y]
                self.counter[x], self.counter[y] = z, z
            if self.rank[x] < self.rank[y]:
                self.par[x] = y
            else:
                self.par[y] = x
                if self.rank[x] == self.rank[y]:
                    self.rank[x] += 1

        def size(self, x):
            x = self.find(x)
            return self.counter[x]

        def same(self, x, y):
            return self.find(x) == self.find(y)

        def Kruskal(self):
            """
            return: 最小全域木のコストの和
            """
            edges = sorted(self.edges, key=lambda x: x[2])  
            res = 0
            for e in edges:
                if not self.same(e[0], e[1]):
                    self.unite(e[0], e[1])
                    res += e[2]
            return res
    N = I()
    X = []
    for i in range(N):
        a, b = LI()
        X.append((a,b))
    P = defaultdict(set)
    for i,x in enumerate(X):
        P[x] = i
    graph = Kruskal_UnionFind(N + 1)

    X.sort(key=lambda x:x[0])
    for i in range(N-1):
        if X[i+1][0]-X[i][0]>abs(X[i+1][1]-X[i][1]):
            continue
        r = X[i+1][0]-X[i][0]
        graph.add(P[X[i]], P[X[i+1]], r)

    X.sort(key=lambda x:x[1])
    for i in range(N-1):
        if X[i+1][1]-X[i][1]>abs(X[i+1][0]-X[i][0]):
            continue
        r = X[i+1][1]-X[i][1]
        graph.add(P[X[i]], P[X[i+1]], r)

    ans = graph.Kruskal()
    print(ans)
    return

def ABC84_D():
    def is_prime(n):
        if n == 1: return False
        for k in range(2, int(math.sqrt(n)) + 1):
            if n % k == 0:
                return False
        return True

    def like_2017(x):
        if is_prime(x) and is_prime(x//2+1):
            return True
        return False

    Q = I()
    maxX = 10**5
    imos = [0]*(maxX+1)
    for i in range(maxX+1):
        if like_2017(i) and i!=2:
            imos[i] = imos[i-1] + 1
        else:
            imos[i] = imos[i - 1]
    L = [LI()for _ in range(Q)]
    ans = []
    for l,r in L:
        cur = imos[r]-imos[l-1]
        ans.append(cur)
    for v in ans:
        print(v)
    return

def ABC34_C():
    
    def cmb(n, r, mod):
        cur = 1
        for i in range(r):
            cur *= (n-i)
            cur %= mod
        for i in range(r):
            cur *= pow(i+1,mod-2,mod)
            cur %= mod
        return cur

    W, H = LI()
    r = W+H-2; l = H-1
    ans = cmb(r,l,mod)
    print(ans)
    return

def ABC145_D():
    def cmb(n, r, mod):
        cur = 1
        for i in range(r):
            cur *= (n-i)
            cur %= mod
        for i in range(r):
            cur *= pow(i+1,mod-2,mod)
            cur %= mod
        return cur

    X, Y = LI()
    if (X+Y)%3!=0:
        print(0)
        return
    r = (X+Y)//3; l = X-(X+Y)//3
    if l<0:
        print(0)
        return
    ans = cmb(r,l,mod)
    print(ans)
    return



def square869120Contest1_E():
    N, Q = LI()
    A = LI()
    C = LI()
    C.append(1)
    L = [0]*N
    for i in range(1,N):
        L[i] = pow(A[i-1],A[i],mod) + L[i-1]
    
    ans = 0
    now = 0
    for i in range(Q+1):
        next = C[i]-1
        cur = abs(L[next]-L[now])
        ans += cur
        ans %= mod
        now = next
        
    print(ans)
    return

import sys,copy,bisect,itertools,heapq,math,random
from heapq import heappop,heappush,heapify
from collections import Counter,defaultdict,deque

import gc
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))
def LSI(): return list(map(str,sys.stdin.readline().split()))
def LS(): return sys.stdin.readline().split()
def SI(): return sys.stdin.readline().strip()
global mod,mod2,inf,alphabet,_ep
mod = 10**9 + 7
mod2 = 998244353
inf = 10**18
_ep = 10**(-12)
alphabet = [chr(ord('a') + i) for i in range(26)]

if __name__ == '__main__':
    ABC145_D()
"""
"""

Solution (Python):


a, b = map(int, input().split())
MOD = int(1e9 + 7)

def calc(x, y):
    right = above = 0
    while x>0 and y>0:
        if x>y:
            x -= 2
            y -= 1
            right += 1
        else:
            x -= 1
            y -= 2
            above += 1

    return (True, right, above) if x==0 and y==0 else (False, None, None)


def res(n, k):
    
    total = 1
    if k < n-k:
        k = n-k
    for i in range(k+1, n+1):
        total = (total * i)% MOD
        total *= pow(i-k, MOD-2, MOD)
    return total

r, right, above = calc(a, b)
if not r:
    print(0)
else:
    print(int(res(above+right, right) % MOD))

Solution (Python):
x,y=map(int,input().split())

if (2*y-x)%3!=0 or (2*x-y)%3!=0 or 2*x-y<0 or 2*y-x<0:
    ans=0
else:
    a=(2*y-x)//3
    b=(2*x-y)//3
    n=a+b
    ans=1
    for i in range(min(a,b)):
        ans*=(n-i)
        ans%=(10**9+7)
        ans*=pow(i+1,10**9+5,10**9+7)
print(ans%(10**9+7))

Solution (Python):
x,y = map(int,input().split())
if (2*x-y)%3 != 0 or 2*x-y < 0:
    print(0)
    exit()
else:
    b = int((2*x-y)/3)
    a = int(x-2*b)
if a < 0:
    print(0)
    exit()
else:
    small = min(a,b)
    bunbo = 1
    bunsi = 1
    sumer = a+b
    for i in range(small):
        bunsi *= sumer-i
        bunsi = bunsi%1000000007
        bunbo *= i+1
        bunbo = bunbo%1000000007
    bunbo = pow(bunbo,1000000005,1000000007)
    ans = (bunsi*bunbo)%1000000007
    print(ans)

Solution (Python):
X,Y = map(int,input().split())
if (X + Y) % 3 != 0:
    print(0)
    exit()
n = (-X+2*Y)//3
m = (2*X-Y)//3
if n < 0 or m < 0:
    print(0)
    exit()

mod = 10**9+7
mod_inv = [0, 1] + [0] * (max(n,m)+3)
for i in range(2, max(n,m)+5):
    mod_inv[i] = - mod_inv[mod % i] * (mod // i) % mod
def comod(n, r, mod):
    ans = 1
    for i in range(r):
        ans *= (n-i) % mod
        ans *= mod_inv[i+1]
        ans %= mod
    return ans
ans = comod(n+m,n,mod)
print(ans)

Solution (Python):
X,Y = map(int,input().split())
if (X + Y) % 3 != 0:
    print(0)
    exit()
n = (-X+2*Y)//3
m = (2*X-Y)//3
if n < 0 or m < 0:
    print(0)
    exit()

mod = 10**9+7
mod_inv = [0, 1] + [0] * (max(n,m)+3)
for i in range(2, max(n,m)+5):
    mod_inv[i] = - mod_inv[mod % i] * (mod // i) % mod
def comod(n, r, mod):
    ans = 1
    for i in range(r):
        ans *= (n-i) % mod
        ans *= mod_inv[i+1]
        ans %= mod
    return ans
ans = comod(n+m,n,mod)
print(ans)

Solution (Python):
x,y= map(int, input().split())
a=min(x,y)
b=max(x,y)
mod=pow(10,9)+7
if b-a>a or (a-(b-a))%3!=0:
    print(0)

else:
    r=(a-(b-a))//3
    l=((a-(b-a))//3)+(b-a)
    c=1
    d=1
    for i in range(r):
        c=(c*(l+r-i))%mod
        d=(d*(r-i))%mod
    ans=c*pow(d,mod-2,mod)
    print(ans%mod)

Solution (Python):

import numpy as np

MOD = 1000000007


class Combination:
    def __init__(self, n):
        self.n = n
        self.fac, self.facinv = self.make_fact(n, MOD)

    def cumprod(self, arr,MOD):
        L = len(arr); Lsq = int(L**.5+1)
        arr = np.resize(arr,Lsq**2).reshape(Lsq,Lsq)
        for n in range(1,Lsq):
            arr[:,n] *= arr[:,n-1]; arr[:,n] %= MOD
        for n in range(1,Lsq):
            arr[n] *= arr[n-1,-1]; arr[n] %= MOD
        return arr.ravel()[:L]
    
    def make_fact(self, U,MOD):
        x = np.arange(U,dtype=np.int64); x[0] = 1
        fact = self.cumprod(x,MOD)
        x = np.arange(U,0,-1,dtype=np.int64); x[0] = pow(int(fact[-1]),MOD-2,MOD)
        fact_inv = self.cumprod(x,MOD)[::-1]
        return fact,fact_inv


    def nck(self, n, k):
        if k == 0 or n == k:
            return 1
        return self.fac[n] * self.facinv[k] % MOD * self.facinv[n-k] % MOD;

    def get(n):
        return self.fac[n]
    
    def getinv(n):
        return self.facinv[n]

if __name__ == "__main__":
    X,Y = map(int, input().split())
    cb = Combination(1000010)
    if (X+Y) % 3 != 0:
        print(0)
        exit(0)
    if X > Y:
        if X > 2*Y:
            print(0)
            exit(0)
    else:
        if Y > 2*X:
            print(0)
            exit(0)
    a = (2 * Y - X) // 3
    b = (2 * X - Y) // 3
    print(cb.nck(a+b, a))