Problem p02862 (C++)

Buggy submission (status: Time Limit Exceeded):
/*
AuThOr GaRyMr
技巧:
1.区别对待大数据&小数据！
2.Dp难推时算贡献！
3.long long (尤其乘法)！
4.long long INF 要大
5.Dp on trees: 换根法，每次清空当前的节点和换到的子节点
6.long double | 输出浮点数
7.注意特判!(prince and princess)
*/
#include <bits/stdc++.h>
#define rb(a, b, c) for (int a = b; a <= c; ++a)
#define rl(a, b, c) for (int a = b; a >= c; --a)
#define niv vector<int>
#define LL long long
#define IT iterator
#define PB push_back
#define II(a, b) make_pair(a, b)
#define FIR first
#define SEC second
#define FREO freopen("check.out", "w", stdout)
#define rep(a, b) for (int a = 0; a < b; ++a)
#define KEEP while (1)
#define SRAND                                                                  \
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng() % a
#define ALL(a) a.begin(), a.end()
#define POB pop_back
using namespace std;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> mp;
typedef pair<mp, mp> superpair;
const int maxn = 1000000;
bool arr[maxn + 1] = {false};
vector<int> produce_prim_number() {
  vector<int> prim;
  prim.push_back(2);
  int i, j;
  for (i = 3; i * i <= maxn; i += 2) {
    if (!arr[i]) {
      prim.push_back(i);
      for (j = i * i; j <= maxn; j += i)
        arr[j] = true;
    }
  }
  while (i < maxn) {
    if (!arr[i])
      prim.push_back(i);
    i += 2;
  }
  return prim;
}
// 计算n!中素数因子p的指数
int cal(int x, int p) {
  int ans = 0;
  long long rec = p;
  while (x >= rec) {
    ans += x / rec;
    rec *= p;
  }
  return ans;
}
// 计算n的k次方对m取模，二分法
int pow(long long n, int k, int M) {
  long long ans = 1;
  while (k) {
    if (k & 1) {
      ans = (ans * n) % M;
    }
    n = (n * n) % M;
    k >>= 1;
  }
  return ans;
}
// 计算C（n，m）
int combination(int n, int m) {
  const int M = 1e9 + 7;
  vector<int> prim = produce_prim_number();
  long long ans = 1;
  int num;
  for (int i = 0; i < prim.size() && prim[i] <= n; ++i) {
    num = cal(n, prim[i]) - cal(m, prim[i]) - cal(n - m, prim[i]);
    ans = (ans * pow(prim[i], num, M)) % M;
  }
  return ans;
}
int main() {
  int x, y;
  cin >> x >> y;
  if ((x + y) % 3 == 0) {
    int Y = (y + y - x) / 3, tot = (x + y) / 3;
    int X = tot - Y;
    if (X < 0) {
      cout << 0 << endl;
      return 0;
    }
    cout << combination(tot, Y) << endl;
  } else {
    cout << 0 << endl;
  }
  return 0;
}


Fixed submission:
/*
AuThOr GaRyMr
技巧:
1.区别对待大数据&小数据！
2.Dp难推时算贡献！
3.long long (尤其乘法)！
4.long long INF 要大
5.Dp on trees: 换根法，每次清空当前的节点和换到的子节点
6.long double | 输出浮点数
7.注意特判!(prince and princess)
*/
#include <bits/stdc++.h>
#define rb(a, b, c) for (int a = b; a <= c; ++a)
#define rl(a, b, c) for (int a = b; a >= c; --a)
#define niv vector<int>
#define LL long long
#define IT iterator
#define PB push_back
#define II(a, b) make_pair(a, b)
#define FIR first
#define SEC second
#define FREO freopen("check.out", "w", stdout)
#define rep(a, b) for (int a = 0; a < b; ++a)
#define KEEP while (1)
#define SRAND                                                                  \
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng() % a
#define ALL(a) a.begin(), a.end()
#define POB pop_back
using namespace std;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> mp;
typedef pair<mp, mp> superpair;
const int maxn = 1000000;
bool arr[maxn + 1] = {false};
vector<int> produce_prim_number() {
  vector<int> prim;
  prim.push_back(2);
  int i, j;
  for (i = 3; i * i <= maxn; i += 2) {
    if (!arr[i]) {
      prim.push_back(i);
      for (j = i * i; j <= maxn; j += i)
        arr[j] = true;
    }
  }
  while (i < maxn) {
    if (!arr[i])
      prim.push_back(i);
    i += 2;
  }
  return prim;
}
// 计算n!中素数因子p的指数
int cal(int x, int p) {
  int ans = 0;
  long long rec = p;
  while (x >= rec) {
    ans += x / rec;
    rec *= p;
  }
  return ans;
}
// 计算n的k次方对m取模，二分法
int pow(long long n, int k, int M) {
  long long ans = 1;
  while (k) {
    if (k & 1) {
      ans = (ans * n) % M;
    }
    n = (n * n) % M;
    k >>= 1;
  }
  return ans;
}
// 计算C（n，m）
int combination(int n, int m) {
  const int M = 1e9 + 7;
  vector<int> prim = produce_prim_number();
  long long ans = 1;
  int num;
  for (int i = 0; i < prim.size() && prim[i] <= n; ++i) {
    num = cal(n, prim[i]) - cal(m, prim[i]) - cal(n - m, prim[i]);
    ans = (ans * pow(prim[i], num, M)) % M;
  }
  return ans;
}
int main() {
  int x, y;
  cin >> x >> y;
  if ((x + y) % 3 == 0) {
    int Y = (y + y - x) / 3, tot = (x + y) / 3;
    int X = tot - Y;
    if (X < 0 || Y < 0) {
      cout << 0 << endl;
      return 0;
    }
    cout << combination(tot, Y) << endl;
  } else {
    cout << 0 << endl;
  }
  return 0;
}