Language: C++

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;




class Program
{




    static void Main(string[] args)
    {
        var waaaa = new waaaa(); 
        waaaa.Solve();

    }

}

public class waaaa 
{
    const int MOD = 1000000007;
    const long INF = 1 << 61;
    const int MOD2 = 998244353;

    Scaner cin = new Scaner();
    write cout = new write();
    Math2 mmath = new Math2();


    public void Solve()
    {
        mmath.FactoricalModSet(1000000);
        

        //ここから
        var o = cin.LongM;
        var X = o[0];
        var Y = o[1];

        if (X == 2 * Y) cout.wri(1);
        else if (Y == 2 * X) cout.wri(1);
        else if (X % 3 != 0 || Y % 3 != 0||X>=3*Y||Y>=3*X) cout.wri(0);
        else cout.wri(mmath.nCr((X + Y) / 3, X / 3));

    }


    public static bool NextPermutation<T>(T[] array, int start, int length)
           where T : IComparable
    {
        int end = start + length - 1;

        // 範囲が狭すぎる
        if (end <= start) return false;

        int last = end;
        while (true)
        {
            int pos = last--;

            if (array[last].CompareTo(array[pos]) < 0)
            {
                int i;
                for (i = end + 1; array[last].CompareTo(array[--i]) >= 0;) { }
                T tmp = array[last]; array[last] = array[i]; array[i] = tmp;
                Array.Reverse(array, pos, end - pos + 1);
                return true;
            }
            if (last == start)  // 最後の順列
            {
                Array.Reverse(array, start, end - start);
                return false;
            }
        }

        // ここに来ることはない
        throw new Exception("NextPermutation: Fatal error");
    }
}







//b-aで降順

//priority queue
class PriorityQueue<T> 
{
    private readonly List<T> heap;
    private readonly Comparison<T> compare;
    private int size;
    public PriorityQueue() : this(Comparer<T>.Default) {} 
    public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
    public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
    public PriorityQueue(int capacity, Comparison<T> comparison)
    {
        this.heap = new List<T>(capacity);
        this.compare = comparison;
    }
    public void Enqueue(T item)
    {
        this.heap.Add(item);
        var i = size++;
        while (i > 0)
        {
            var p = (i - 1) >> 1;
            if (compare(this.heap[p], item) <= 0)
                break;
            this.heap[i] = heap[p];
            i = p;
        }
        this.heap[i] = item;

    }
    public T Dequeue()
    {
        var ret = this.heap[0];
        var x = this.heap[--size];
        var i = 0;
        while ((i << 1) + 1 < size)
        {
            var a = (i << 1) + 1;
            var b = (i << 1) + 2;
            if (b < size && compare(heap[b], heap[a]) < 0) a = b;
            if (compare(heap[a], x) >= 0)
                break;
            heap[i] = heap[a];
            i = a;
        }
        heap[i] = x;
        heap.RemoveAt(size);
        return ret;
    }
    public T Peek() { return heap[0]; }
    public int Count { get { return size; } }
    public bool Any() { return size > 0; }
}


 public class Math2
{
    public long[] Fact;  //Nまでの階乗
    public long[] invFact;  //階乗の逆元

    //Nまでの階乗をセットしておく
    public void FactoricalModSet(long N,long MOD=1000000007)
    {
        Fact = new long[N + 1];
        invFact = new long[N + 1];

        Fact[0] = 1;
        for(long i = 1; i <= N; ++i)
        {
            Fact[i] = Fact[i - 1] * i%MOD;
        }
        invFact[N] = pow(Fact[N], MOD - 2);

        for (long i = N; i > 0; --i)
        {
            invFact[i - 1] = invFact[i] * i%MOD;
        }

    }

    //nCr 引数:n r (mod)
    public long nCr(long n,long r,long MOD=1000000007)
    {
        return (Fact[n] * invFact[r] % MOD * invFact[n-r]%MOD);
    }

    //階乗(O(logN)) 引数:底x n乗　(MOD)
    public long pow(long x,long n,long MOD = 1000000007)
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) != 0) res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }

    //最大公約数 引数:整数x,y
    public long GCD(long x, long y)
    {
        while (y != 0)
        {
            var r = x % y;
            x = y;
            y = r;
        }
        return x;
    }

    //最小公倍数 引数:整数x,y
    public long LCM(long x, long y)
    {
        return x * y / GCD(x, y);
    }

    //素因数分解 引数:整数N
    public Dictionary<long,int > PrimeFactorization(long N)
    {
        var ret = new Dictionary<long,int>();

        for(long i = 2; i*i <= N; ++i)
        {
            int cnt = 0;
            while (N % i == 0)
            {
                cnt++;
                N /= i;
            }
            if (cnt != 0) ret[i] = cnt;

        }
        if (N >= 2)ret[N]=1;

        return ret;

    }
    public List<long> PrimeFactorization2(long N)
    {
        var ret = new List<long>();

        for (long i = 1; i * i <= N; ++i)
        {

            if (N % i == 0)
            {
                ret.Add(i);
                ret.Add(N / i);
            }

        }

        return ret;

    }

}


namespace CompLib.Algorithms
{

    #region BinarySearch
    public static partial class Algorithm
    {
        static int binarySearch<T>(IList<T> a, T v, IComparer<T> cmp, bool islb)
        {
            var l = 0;
            var r = a.Count - 1;
            while (l <= r)
            {
                var m = (l + r) / 2;
                var res = cmp.Compare(a[m], v);
                if (res < 0 || (res == 0 && !islb)) l = m + 1;
                else r = m - 1;
            }
            return l;
        }

        /// <summary>
        /// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int LowerBound<T>(this IList<T> a, T v, Comparison<T> f) { return binarySearch(a, v, Comparer<T>.Create(f), true); }

        /// <summary>
        ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int LowerBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, true); }

        /// <summary>
        /// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int UpperBound<T>(this IList<T> a, T v, Comparison<T> cmp) { return binarySearch(a, v, Comparer<T>.Create(cmp), false); }

        /// <summary>
        ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> より真に大きい要素が現れる最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int UpperBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, false); }

    }
    #endregion
}







class Scaner
{
    public string Str => Console.ReadLine();

    public string[] StrM => Str.Split(' ');

    public long[] LongM => StrM.Select(long.Parse).ToArray();
    public int[] IntM => StrM.Select(int.Parse).ToArray();
    public char[] CharM => Str.ToArray();
    public long Long1 => LongM[0];
    public int Int1 => IntM[0];
    
}



class write
{
    public  void wri<T>(T x)
    {
        Console.WriteLine(x);
    }
}



Compiler output:
a.cc:257:6: error: invalid preprocessing directive #region
  257 |     #region BinarySearch
      |      ^~~~~~
a.cc:319:6: error: invalid preprocessing directive #endregion
  319 |     #endregion
      |      ^~~~~~~~~
a.cc:1:7: error: expected nested-name-specifier before 'System'
    1 | using System;
      |       ^~~~~~
a.cc:2:7: error: expected nested-name-specifier before 'System'
    2 | using System.Collections.Generic;
      |       ^~~~~~
a.cc:3:7: error: expected nested-name-specifier before 'System'
    3 | using System.Linq;
      |       ^~~~~~
a.cc:4:7: error: expected nested-name-specifier before 'System'
    4 | using System.Text;
      |       ^~~~~~
a.cc:5:7: error: expected nested-name-specifier before 'System'
    5 | using System.Threading.Tasks;
      |       ^~~~~~
a.cc:16:22: error: 'string' has not been declared
   16 |     static void Main(string[] args)
      |                      ^~~~~~
a.cc:16:31: error: expected ',' or '...' before 'args'
   16 |     static void Main(string[] args)
      |                               ^~~~
a.cc:23:2: error: expected ';' after class definition
   23 | }
      |  ^
      |  ;
a.cc: In static member function 'static void Program::Main(int*)':
a.cc:18:9: error: 'var' was not declared in this scope
   18 |         var waaaa = new waaaa();
      |         ^~~
a.cc:19:9: error: 'waaaa' was not declared in this scope
   19 |         waaaa.Solve();
      |         ^~~~~
a.cc: At global scope:
a.cc:25:1: error: expected unqualified-id before 'public'
   25 | public class waaaa
      | ^~~~~~
a.cc:96:7: error: 'PriorityQueue' is not a class template
   96 | class PriorityQueue<T>
      |       ^~~~~~~~~~~~~
a.cc:96:21: error: 'T' was not declared in this scope
   96 | class PriorityQueue<T>
      |                     ^
a.cc:98:12: error: expected ':' before 'readonly'
   98 |     private readonly List<T> heap;
      |            ^~~~~~~~~
      |            :
a.cc:98:13: error: 'readonly' does not name a type
   98 |     private readonly List<T> heap;
      |             ^~~~~~~~
a.cc:99:12: error: expected ':' before 'readonly'
   99 |     private readonly Comparison<T> compare;
      |            ^~~~~~~~~
      |            :
a.cc:99:13: error: 'readonly' does not name a type
   99 |     private readonly Comparison<T> compare;
      |             ^~~~~~~~
a.cc:100:12: error: expected ':' before 'int'
  100 |     private int size;
      |            ^~~~
      |            :
a.cc:101:11: error: expected ':' before 'PriorityQueue'
  101 |     public PriorityQueue() : this(Comparer<T>.Default) {}
      |           ^~~~~~~~~~~~~~
      |           :
a.cc:102:11: error: expected ':' before 'PriorityQueue'
  102 |     public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
      |           ^~~~~~~~~~~~~~
      |           :
a.cc:102:35: error: expected ')' before '<' token
  102 |     public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
      |                         ~         ^
      |                                   )
a.cc:103:11: error: expected ':' before 'PriorityQueue'
  103 |     public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
      |           ^~~~~~~~~~~~~~
      |           :
a.cc:103:36: error: expected ')' before '<' token
  103 |     public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
      |                         ~          ^
      |                                    )
a.cc:104:11: error: expected ':' before 'PriorityQueue'
  104 |     public PriorityQueue(int capacity, Comparison<T> comparison)
      |           ^~~~~~~~~~~~~~
      |           :
a.cc:104:40: error: 'Comparison' has not been declared
  104 |     public PriorityQueue(int capacity, Comparison<T> comparison)
      |                                        ^~~~~~~~~~
a.cc:104:50: error: expected ',' or '...' before '<' token
  104 |     public PriorityQueue(int capacity, Comparison<T> comparison)
      |                                                  ^
a.cc:109:11: error: expected ':' before 'void'
  109 |     public void Enqueue(T item)
      |           ^~~~~
      |           :
a.cc:109:25: error: 'T' has not been declared
  109 |     public void Enqueue(T item)
      |                         ^
a.cc:124:11: error: expected ':' before 'T'
  124 |     public T Dequeue()
      |           ^~
      |           :
a.cc:124:12: error: 'T' does not name a type
  124 |     public T Dequeue()
      |            ^
a.cc:143:11: error: expected ':' before 'T'
  143 |     public T Peek() { return heap[0]; }
      |           ^~
      |           :
a.cc:143:12: error: 'T' does not name a type
  143 |     public T Peek() { return heap[0]; }
      |            ^
a.cc:144:11: error: expected ':' before 'int'
  144 |     public int Count { get { return size; } }
      |           ^~~~
      |           :
a.cc:144:45: error: expected ';' at end of member declaration
  144 |     public int Count { get { return size; } }
      |                                             ^
      |                                              ;
a.cc:145:11: error: expected ':' before 'bool'
  145 |     public bool Any() { return size > 0; }
      |           ^~~~~
      |           :
a.cc:146:2: error: expected ';' after class definition
  146 | }
      |  ^
      |  ;
a.cc:144:24: error: 'get' was not declared in this scope
  144 |     public int Count { get { return size; } }
      |                        ^~~
a.cc:144:28: error: expected '}' before '{' token
  144 |     public int Count { get { return size; } }
      |                            ^
a.cc:144:22: note: to match this '{'
  144 |     public int Count { get { return size; } }
      |                      ^
a.cc:144:28: error: cannot convert '<brace-enclosed initializer list>' to 'int' in initialization
  144 |     public int Count { get { return size; } }
      |                            ^
a.cc:144:28: error: expected ';' before '{' token
a.cc: In constructor 'PriorityQueue::PriorityQueue()':
a.cc:101:30: error: expected identifier before 'this'
  101 |     public PriorityQueue() : this(Comparer<T>.Default) {}
      |                              ^~~~
a.cc:101:30: error: expected '{' before 'this'
a.cc: In constructor 'PriorityQueue::PriorityQueue(int, int)':
a.cc:106:14: error: request for member 'heap' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  106 |         this.heap = new List<T>(capacity);
      |              ^~~~
a.cc:106:25: error: 'List' does not name a type
  106 |         this.heap = new List<T>(capacity);
      |                         ^~~~
a.cc:106:30: error: 'T' was not declared in this scope
  106 |         this.heap = new List<T>(capacity);
      |                              ^
a.cc:107:14: error: request for member 'compare' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  107 |         this.compare = comparison;
      |              ^~~~~~~
a.cc:107:24: error: 'comparison' was not declared in this scope
  107 |         this.compare = comparison;
      |                        ^~~~~~~~~~
a.cc: In member function 'void PriorityQueue::Enqueue(int)':
a.cc:111:14: error: request for member 'heap' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  111 |         this.heap.Add(item);
      |              ^~~~
a.cc:112:9: error: 'var' was not declared in this scope
  112 |         var i = size++;
      |         ^~~
a.cc:113:16: error: 'i' was not declared in this scope
  113 |         while (i > 0)
      |                ^
a.cc:115:17: error: expected ';' before 'p'
  115 |             var p = (i - 1) >> 1;
      |                 ^
a.cc:116:30: error: request for member 'heap' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  116 |             if (compare(this.heap[p], item) <= 0)
      |                              ^~~~
a.cc:116:35: error: 'p' was not declared in this scope
  116 |             if (compare(this.heap[p], item) <= 0)
      |                                   ^
a.cc:116:17: error: 'compare' was not declared in this scope
  116 |             if (compare(this.heap[p], item) <= 0)
      |                 ^~~~~~~
a.cc:118:18: error: request for member 'heap' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  118 |             this.heap[i] = heap[p];
      |                  ^~~~
a.cc:118:28: error: 'heap' was not declared in this scope
  118 |             this.heap[i] = heap[p];
      |                            ^~~~
a.cc:118:33: error: 'p' was not declared in this scope
  118 |             this.heap[i] = heap[p];
      |                                 ^
a.cc:121:14: error: request for member 'heap' in '(PriorityQueue*)this', which is of pointer type 'PriorityQueue*' (maybe you meant to use '->' ?)
  121 |         this.heap[i] = item;
      |              ^~~~
a.cc:121:19: error: 'i' was not declared in this scope
  121 |         this.heap[i] = item;
      |                   ^
a.cc: At global scope:
a.cc:149:2: error: expected unqualified-id before 'public'
  149 |  public class Math2
      |  ^~~~~~
a.cc:254:18: error: expected '{' before '.' token
  254 | namespace CompLib.Algorithms
      |                  ^
a.cc:254:18: error: expected unqualified-id before '.' token
a.cc:330:11: error: expected ':' before 'string'
  330 |     public string Str => Console.ReadLine();
      |           ^~~~~~~
      |           :
a.cc:330:12: error: 'string' does not name a type
  330 |     public string Str => Console.ReadLine();
      |            ^~~~~~
a.cc:332:11: error: expected ':' before 'string'
  332 |     public string[] StrM => Str.Split(' ');
      |           ^~~~~~~
      |           :
a.cc:332:12: error: 'string' does not name a type
  332 |     public string[] StrM => Str.Split(' ');
      |            ^~~~~~
a.cc:334:11: error: expected ':' before 'long'
  334 |     public long[] LongM => StrM.Select(long.Parse).ToArray();
      |           ^~~~~
      |           :
a.cc:334:16: error: