#include <iostream>
#include <iomanip>
#include <vector>
#include <string>

#include <algorithm>
#include <numeric>
#include <cmath>
#include <stack>

using namespace std;
typedef long long ll;
const long double PI = (acos(-1));
const long long MOD = 1000000007;
#define rep(i,n) REP(i,0,n)
#define REP(i,x,n) for(int i=x;i<n;++i)

///////////////////////////////////////////////////
// -------------------- I/O -------------------- //
///////////////////////////////////////////////////
// https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords
template<typename T> void outputVec(const std::vector<T>& vec, const int precision = 0) {
	if (precision > 0) std::cout << std::fixed << std::setprecision(precision);
	for (auto it = vec.begin(); it != vec.end() - 1; ++it) { std::cout << *it << " "; }
	std::cout << *(vec.end() - 1) << "\n";
}
template<typename T> void outputVal(const T& res, const int precision = 0) {
	if (precision > 0) std::cout << std::fixed << std::setprecision(precision);
	std::cout << res << "\n";
}
template<typename T> T inputVal() { T a; std::cin >> a; return a; }
template<typename T> std::vector<T> inputVec(T N) {
	std::vector<T> vec(N);
	for (auto it = vec.begin(); it != vec.end(); ++it) { std::cin >> *it; }
	return vec;
}
template<typename T> void inputVec(std::vector<T>& vec) {
	for (auto it = vec.begin(); it != vec.end(); ++it) { std::cin >> *it; }
}

///////////////////////////////////////////////////
// ------------------- utils ------------------- //
///////////////////////////////////////////////////
// change min/max
template<class T> inline bool chMin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chMax(T& a, T b) { if (a < b) { a = b; return true; } return false; }

//void dfs(const ll i, const ll j, const ll x, const ll y, ll& cnt) {
//	// end
//	if (i > x) return;
//	if (j > y) return;
//
//	// found
//	if ((i == x) && (j == y)) {
//		++cnt;
//		return;
//	}
//
//	// next
//	dfs(i+1, j+2, x, y, cnt);
//	dfs(i+2, j+1, x, y, cnt);
//}
//
//
/////////////////////////////////////////////////////
//// ------------------- main -------------------- //
/////////////////////////////////////////////////////
//void Main() {
//
//	const ll nmod = 1000000007;
//
//	const ll x = inputVal<long long>();
//	const ll y = inputVal<long long>();
//
//	ll cnt = 0;
//	dfs(0, 0, x, y, cnt);
//
//	ll ret = cnt % nmod;
//
//	std::cout << ret << std::endl;
//
//	double tmp;
//	cin >> tmp;
//}

//void dfs(const ll x, const ll y, ll& cnt, stack< pair<ll,ll> >& stpos) {
//	const ll i = stpos.top().first;
//	const ll j = stpos.top().second;
//	stpos.pop();
//
//
//	// end
//	if ((i > x) || (j > y)) {
//		return;
//	}
//
//	// found
//	if ((i == x) && (j == y)) {
//		++cnt;
//		return;
//	}
//
//	// next
//	stpos.push(make_pair(i + 1, j + 2));
//	stpos.push(make_pair(i + 2, j + 1));
//}
//
//
/////////////////////////////////////////////////////
//// ------------------- main -------------------- //
/////////////////////////////////////////////////////
//void Main() {
//
//	const ll nmod = 1000000007;
//
//	const ll x = inputVal<long long>();
//	const ll y = inputVal<long long>();
//
//	ll cnt = 0;
//	stack<pair<ll, ll>> stpos;
//	stpos.push(make_pair(2, 1));
//	stpos.push(make_pair(1, 2));
//
//	while (!stpos.empty()) {
//		dfs(x, y, cnt, stpos);
//	}
//
//	ll ret = cnt % nmod;
//
//	std::cout << ret << std::endl;
//
//	double tmp;
//	cin >> tmp;
//}

ll factorial(const ll n, const ll mod =1) {
	ll ret = 1;
	for (int i = 1; i <= n; ++i) {
		ret = (ret * i) % mod;
	}
	return ret;
}

long long modinv(long long a, long long m) {
	long long b = m, u = 1, v = 0;
	while (b) {
		long long t = a / b;
		a -= t * b; swap(a, b);
		u -= t * v; swap(u, v);
	}
	u %= m;
	if (u < 0) u += m;
	return u;
}

void COMinit(std::vector<long long>& fac, std::vector<long long>& finv, std::vector<long long>& inv, int n, int MOD) {
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for (int i = 2; i < n; i++) {
		fac[i] = fac[i - 1] * i % MOD;
		inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
		finv[i] = finv[i - 1] * inv[i] % MOD;
	}
}

// binominal coefficient
// http://drken1215.hatenablog.com/entry/2018/06/08/210000
long long COM(int n, int k, int MOD) {
	if (n < k) return 0;
	if (n < 0 || k < 0) return 0;
	std::vector<long long> fac(n+1), finv(n+1), inv(n+1);
	COMinit(fac, finv, inv, n+1, MOD);
	return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}


///////////////////////////////////////////////////
// ------------------- main -------------------- //
///////////////////////////////////////////////////
void Main() {

	const ll MOD = 1000000007;

	const ll x = inputVal<long long>();
	const ll y = inputVal<long long>();

	if ((x + y) % 3 != 0) {
		outputVal(0);
		return;
	}

	// 2n + m  = X
	// n  + 2m = Y
	const ll n = (2 * x - y) / 3;
	const ll m = (2 * y - x) / 3;
	if ((n < 0) || (m < 0)) {
		outputVal(0);
		return;
	}

	const ll nmfact = factorial(n + m, MOD);
	const ll ninv = modinv(n,MOD);
	const ll minv = modinv(m,MOD);
	// const ll ret = (nmfact*ninv*minv) % nmod;
	const ll ret = COM(n + m, n, MOD);
	// const ll ret = comb((n + m), n) % nmod;

	std::cout << ret << std::endl;
}


int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout << std::fixed << std::setprecision(15);
	Main();

	double tmp;
	cin >> tmp;

	return 0;
}


Measured memory_bytes: 15872