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 in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using static System.Console;

public static class Program
{
    private static readonly long INF = long.MaxValue / 2;
    private static readonly int MOD = 1000000007;

    struct Pair<T, U> : IComparable<Pair<T, U>>
        where T : IComparable<T>
        where U : IComparable<U>
    {
        public T first;
        public U second;
        private bool CompWithFirst;

        public Pair(T f, U s, int comp)
        {
            first = f;
            second = s;
            CompWithFirst = comp == 1;
        }

        public int CompareTo(Pair<T, U> other)
        {
            return CompWithFirst ? first.CompareTo(other.first) : second.CompareTo(other.second);
        }
    }

    public class PriorityQueue<T> where T : IComparable<T>
    {

        private List<T> Q;
        private readonly int r;

        public PriorityQueue(bool ascending)
        {
            if (ascending)
            {
                r = 1;
            }
            else
            {
                r = -1;
            }

            Q = new List<T>();
        }


        private void PushHeap(List<T> list, T item)
        {
            int n = list.Count();
            list.Add(item);

            while (n != 0)
            {
                int pIndex = (n - 1) / 2;

                if (list[n].CompareTo(list[pIndex]) * r > 0)
                {
                    Swap(Q, n, pIndex);
                }
                else
                {
                    break;
                }

                n = pIndex;
            }
        }

        private void PopHeap(List<T> list)
        {
            int n = list.Count() - 1;
            list[0] = list[n];
            list.RemoveAt(n);

            int cur = 0;
            int comp;

            while (2 * cur + 1 <= n - 1)
            {
                int c1 = 2 * cur + 1;
                int c2 = 2 * (cur + 1);
                if (c1 == n - 1)
                {
                    comp = c1;
                }
                else
                {

                    comp = list[c1].CompareTo(list[c2]) * r > 0 ? c1 : c2;
                }

                if (list[cur].CompareTo(list[comp]) * r < 0)
                {
                    Swap(Q, cur, comp);
                }
                else
                {
                    break;
                }

                cur = comp;
            }
        }

        private void Swap(List<T> list, int a, int b)
        {
            T keep = list[a];
            list[a] = list[b];
            list[b] = keep;
        }



        public void Enqueue(T value)
        {
            PushHeap(Q, value);
        }

        public T Dequeue()
        {
            T ret = Q[0];
            PopHeap(Q);
            return ret;
        }

        public T Peek()
        {
            return Q[0];
        }

        public int CountItem()
        {
            return Q.Count();
        }
    }

    static long ModInv(long a, long m)
    {
        long b = m, u = 1, v = 0;
        while (b != 0)
        {
            long t = a / b;
            a -= t * b;
            long tmp = a;
            a = b;
            b = tmp;
            u -= t * v;
            tmp = u;
            u = v;
            v = tmp;
        }

        u %= m;
        if (u < 0) u += m;
        return u;
    }

    public static long CalcComb(long n, long m)
    {
        //条件チェック
        if (n < m) return 0;
        if (n < 0 || m < 0) return 0;

        //nＣm ＝ nＣm-1 ×（n-m+1）/ m 
//         return CalcFact(n) / (CalcFact(m) * CalcFact(n - m));
        //MODで割ってbの逆元を求める
        return CalcFact(n) * ModInv((CalcFact(m) * CalcFact(n - m)) % MOD, MOD) % MOD;
    }

    /// <summary>
    /// 階乗を計算する。
    /// </summary>
    /// <param name="n">n</param>
    /// <returns>nの階乗（n!）</returns>
    public static long CalcFact(long n)
    {
        if (n <= 0)
        {
            return 1;
        }

        return n * CalcFact(n - 1) % MOD;
    }


    struct Pos
    {
        public int x;
        public int y;

        public Pos(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        
        public static Pos operator +(Pos p1, Pos p2)
        {
            var result = new Pos();
            result.x = p2.x + p1.x;
            result.y = p2.y + p1.y;
            return result;
        }

        public static Pos operator -(Pos p1, Pos p2)
        {
            var result = new Pos();
            result.x = p2.x - p1.x;
            result.y = p2.y - p1.y;
            return result;
        }
    }
    
    class Modular
    {
        private const int M = 1000000007;
        private long value;

        public Modular(long value)
        {
            this.value = value;
        }

        public static implicit operator Modular(long a)
        {
            var m = a % M;
            return new Modular((m < 0) ? m + M : m);
        }

        public static Modular operator +(Modular a, Modular b)
        {
            return a.value + b.value;
        }

        public static Modular operator -(Modular a, Modular b)
        {
            return a.value - b.value;
        }

        public static Modular operator *(Modular a, Modular b)
        {
            return a.value * b.value;
        }

        private static Modular Pow(Modular a, int n)
        {
            switch (n)
            {
                case 0:
                    return 1;
                case 1:
                    return a;
                default:
                    var p = Pow(a, n / 2);
                    return p * p * Pow(a, n % 2);
            }
        }

        public static Modular operator /(Modular a, Modular b)
        {
            return a * Pow(b, M - 2);
        }

        private static readonly List<int> facs = new List<int> {1};

        private static Modular Fac(int n)
        {
            for (int i = facs.Count; i <= n; ++i)
            {
                facs.Add((int) (Math.BigMul(facs.Last(), i) % M));
            }

            return facs[n];
        }

        public static Modular Ncr(int n, int r)
        {
            return (n < r) ? 0
                : (n == r) ? 1
                : Fac(n) / (Fac(r) * Fac(n - r));
        }

        public static explicit operator int(Modular a)
        {
            return (int) a.value;
        }
    }
    
    static class Permutation<T>
    {
        private static void Search(List<T[]> perms, Stack<T> stack, T[] a)
        {
            int N = a.Length;
            if (N == 0)
            {
                perms.Add(stack.Reverse().ToArray());
            }
            else
            {
                var b = new T[N - 1];
                Array.Copy(a, 1, b, 0, N - 1);
                for (int i = 0; i < a.Length; ++i)
                {
                    stack.Push(a[i]);
                    Search(perms, stack, b);
                    if (i < b.Length) { b[i] = a[i]; }
                    stack.Pop();
                }
            }
        }
        public static IEnumerable<T[]> All(IEnumerable<T> src)
        {
            var perms = new List<T[]>();
            Search(perms, new Stack<T>(), src.ToArray());
            return perms;
        }
    }

    public static void Main(string[] args)
    {
        var input = ReadLine().Split(' ').Select(int.Parse).ToArray();
        int x = input[0];
        int y = input[1];

        if ((x + y) % 3 != 0)
        {
            WriteLine(0);
            return;
        }
        
        // n+2m=X 2n+m=Y
        int n = (2 * y - x) / 3;
        int m = y - 2 * n;
        
        WriteLine(CalcComb(n+m, n));
    }
}