Problem p02862 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

#define CPP_STR(x) CPP_STR_I(x)
#define CPP_CAT(x, y) CPP_CAT_I(x, y)
#define CPP_STR_I(args...) #args
#define CPP_CAT_I(x, y) x##y

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;

using f32 = float;
using f64 = double;

#define FOR(i, start, end)                                                     \
  for (i64 i = (start), CPP_CAT(i, xxxx_end) = (end);                          \
       i < CPP_CAT(i, xxxx_end); ++i)
#define REP(i, n) FOR(i, 0, n)
#define REPS(i, n) for (i64 i = 1; i <= n; ++i)
#define RREP(i, n) for (i64 i = n - 1; i >= 0; --i)
#define RREPS(i, n) for (i64 i = n; i >= 1; --i)

#define ALL(f, c, ...)                                                         \
  (([&](decltype((c)) cccc) {                                                  \
    return (f)(std::begin(cccc), std::end(cccc), ##__VA_ARGS__);               \
  })(c))

#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());

#define pb push_back
#define mp make_pair
#define F first
#define S second

template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

template <typename C> i64 SIZE(const C &c) {
  return static_cast<i64>(c.size());
}

template <typename T, size_t N> i64 SIZE(const T (&)[N]) {
  return static_cast<i64>(N);
}

struct ProconInit {
  static constexpr int IOS_PREC = 15;
  static constexpr bool AUTOFLUSH = false;

  ProconInit() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(IOS_PREC);
    if (AUTOFLUSH)
      cout << unitbuf;
  }
} PROCON_INIT;

template <int MOD> struct Fp {
  i64 val;
  constexpr Fp(i64 v = 0) noexcept : val(v % MOD) {
    if (val < 0)
      val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator-() const noexcept { return val ? MOD - val : 0; }
  constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
  constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
  constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
  constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
  constexpr Fp &operator+=(const Fp &r) noexcept {
    val += r.val;
    if (val >= MOD)
      val -= MOD;
    return *this;
  }
  constexpr Fp &operator-=(const Fp &r) noexcept {
    val -= r.val;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr Fp &operator*=(const Fp &r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp &operator/=(const Fp &r) noexcept {
    i64 a = r.val, b = MOD, u = 1, v = 0;
    while (b) {
      i64 t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % MOD;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr bool operator==(const Fp &r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator!=(const Fp &r) const noexcept {
    return this->val != r.val;
  }
  constexpr bool operator>(const Fp &r) const noexcept {
    return this->val > r.val;
  }
  constexpr bool operator>=(const Fp &r) const noexcept {
    return this->val >= r.val;
  }
  friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept {
    return os << x.val;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, i64 n) noexcept {
    if (n == 0)
      return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1)
      t = t * a;
    return t;
  }
};

#define MAX_X 1'000'000
#define MAX_Y 1'000'000
#define MOD 1'000'000'007
i64 X, Y;
i64 dx[] = {1, 2};
i64 dy[] = {2, 1};

// a + 2b = X
// 2a + b = Y
// a = X - 2b
// 2(X - 2b) + b = Y
// 2X - 3b = Y
// b = (2X - Y) / 3
// a = -X/3 + 2Y/3

using mint = Fp<MOD>;
mint fact[3 * MAX_X];

mint modfact(i64 n) {
  if (fact[n] > (mint)0)
    return fact[n];

  mint p = 1;
  REPS(i, n) {
    p *= (mint)i;
    fact[i] = p;
  }

  return fact[n] = p;
}

mint modcomb(i64 n, i64 k) {
  if (n < k)
    return (mint)0;
  return modfact(n) / (modfact(k) * modfact(n - k));
}

void solve() {
  fill(fact, fact + 3 * MAX_X, 0);

  i64 a = (2 * Y - X) / 3;
  i64 b = (2 * X - Y) / 3;
  i64 x = a * dx[0] + b * dx[1];
  i64 y = a * dy[0] + b * dy[1];

  if (x != X || y != Y) {
    cout << 0 << endl;
    return;
  }

  mint ans = modcomb(a + b, a);
  cout << ans << endl;
}

int main() {
  cin >> X >> Y;

  solve();

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define CPP_STR(x) CPP_STR_I(x)
#define CPP_CAT(x, y) CPP_CAT_I(x, y)
#define CPP_STR_I(args...) #args
#define CPP_CAT_I(x, y) x##y

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;

using f32 = float;
using f64 = double;

#define FOR(i, start, end)                                                     \
  for (i64 i = (start), CPP_CAT(i, xxxx_end) = (end);                          \
       i < CPP_CAT(i, xxxx_end); ++i)
#define REP(i, n) FOR(i, 0, n)
#define REPS(i, n) for (i64 i = 1; i <= n; ++i)
#define RREP(i, n) for (i64 i = n - 1; i >= 0; --i)
#define RREPS(i, n) for (i64 i = n; i >= 1; --i)

#define ALL(f, c, ...)                                                         \
  (([&](decltype((c)) cccc) {                                                  \
    return (f)(std::begin(cccc), std::end(cccc), ##__VA_ARGS__);               \
  })(c))

#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());

#define pb push_back
#define mp make_pair
#define F first
#define S second

template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

template <typename C> i64 SIZE(const C &c) {
  return static_cast<i64>(c.size());
}

template <typename T, size_t N> i64 SIZE(const T (&)[N]) {
  return static_cast<i64>(N);
}

struct ProconInit {
  static constexpr int IOS_PREC = 15;
  static constexpr bool AUTOFLUSH = false;

  ProconInit() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(IOS_PREC);
    if (AUTOFLUSH)
      cout << unitbuf;
  }
} PROCON_INIT;

template <int MOD> struct Fp {
  i64 val;
  constexpr Fp(i64 v = 0) noexcept : val(v % MOD) {
    if (val < 0)
      val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator-() const noexcept { return val ? MOD - val : 0; }
  constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
  constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
  constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
  constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
  constexpr Fp &operator+=(const Fp &r) noexcept {
    val += r.val;
    if (val >= MOD)
      val -= MOD;
    return *this;
  }
  constexpr Fp &operator-=(const Fp &r) noexcept {
    val -= r.val;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr Fp &operator*=(const Fp &r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp &operator/=(const Fp &r) noexcept {
    i64 a = r.val, b = MOD, u = 1, v = 0;
    while (b) {
      i64 t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % MOD;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr bool operator==(const Fp &r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator!=(const Fp &r) const noexcept {
    return this->val != r.val;
  }
  constexpr bool operator>(const Fp &r) const noexcept {
    return this->val > r.val;
  }
  constexpr bool operator>=(const Fp &r) const noexcept {
    return this->val >= r.val;
  }
  friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept {
    return os << x.val;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, i64 n) noexcept {
    if (n == 0)
      return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1)
      t = t * a;
    return t;
  }
};

#define MAX_X 1'000'000
#define MAX_Y 1'000'000
#define MOD 1'000'000'007
i64 X, Y;
i64 dx[] = {1, 2};
i64 dy[] = {2, 1};

// a + 2b = X
// 2a + b = Y
// a = X - 2b
// 2(X - 2b) + b = Y
// 2X - 3b = Y
// b = (2X - Y) / 3
// a = -X/3 + 2Y/3

using mint = Fp<MOD>;
mint fact[3 * MAX_X];

mint modfact(i64 n) {
  if (fact[n] > (mint)0)
    return fact[n];

  mint p = 1;
  REPS(i, n) {
    p *= (mint)i;
    fact[i] = p;
  }

  return fact[n] = p;
}

mint modcomb(i64 n, i64 k) {
  if (n < k)
    return (mint)0;
  return modfact(n) / (modfact(k) * modfact(n - k));
}

void solve() {
  fill(fact, fact + 3 * MAX_X, 0);

  i64 a = (2 * Y - X) / 3;
  i64 b = (2 * X - Y) / 3;
  i64 x = a * dx[0] + b * dx[1];
  i64 y = a * dy[0] + b * dy[1];

  if (x != X || y != Y) {
    cout << 0 << endl;
    return;
  }

  mint ans;
  if (a < 0 || b < 0) {
    ans = 0;
  } else {
    ans = modcomb(a + b, a);
  }
  cout << ans << endl;
}

int main() {
  cin >> X >> Y;

  solve();

  return 0;
}