Problem p02862 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;
using ll = long long;
using Pii = pair<int, int>;
using Pll = pair<ll, ll>;
template <class T> using Vvec = vector<vector<T>>;

constexpr long long default_mod = 1e9 + 7;

// element of Z/pZ
class Modulo {
public:
  long long p;
  long long n;

  Modulo(long long n0, long long p0);

  bool operator==(const Modulo rhs) const { return n == rhs.n; }
  Modulo &operator+=(const long long rhs);
  Modulo &operator+=(const Modulo &rhs);
  Modulo &operator*=(const long long rhs);
  Modulo &operator*=(const Modulo &rhs);
  Modulo &operator-=(const long long rhs);
  Modulo &operator-=(const Modulo &rhs);
  Modulo pow(const long long k) const;
  Modulo inverse() const;
  Modulo &operator/=(const long long rhs);
  Modulo &operator/=(const Modulo &rhs);
  long long get() const { return n; };
};

const Modulo operator+(const Modulo &lhs, const Modulo &rhs);
const Modulo operator+(const Modulo &lhs, const long long rhs);
const Modulo operator+(const long long lhs, const Modulo &rhs);
const Modulo operator*(const Modulo &lhs, const Modulo &rhs);
const Modulo operator*(const Modulo &lhs, const long long rhs);
const Modulo operator*(const long long lhs, const Modulo &rhs);

template <class T> T ext_gcd(T a, T b, T &x, T &y);

// constructor
Modulo::Modulo(long long n0, long long p0 = default_mod) : p(p0) {
  n = n0 >= 0 ? n0 % p : (p - (-n0 % p)) % p;
}

// operator +=
inline Modulo &Modulo::operator+=(const long long rhs) {
  long long rhs1 = rhs >= 0 ? rhs % p : (p - (-rhs % p)) % p;
  n = (n + rhs1) % p;
  return *this;
}

inline Modulo &Modulo::operator+=(const Modulo &rhs) {
  (*this) += rhs.n;
  return *this;
}

// operator *=
inline Modulo &Modulo::operator*=(const long long rhs) {
  long long rhs1 = rhs >= 0 ? rhs % p : (p - (-rhs % p)) % p;
  n = (n * rhs1) % p;
  return *this;
}

inline Modulo &Modulo::operator*=(const Modulo &rhs) {
  (*this) *= rhs.n;
  return *this;
}

// operator -=
inline Modulo &Modulo::operator-=(const long long rhs) { return *this += -rhs; }

inline Modulo &Modulo::operator-=(const Modulo &rhs) {
  (*this) -= rhs.get();
  return *this;
}

//(*this)**k
Modulo Modulo::pow(const long long k) const {
  if (k == 0)
    return Modulo(1, p);
  if (k == 1)
    return Modulo(n, p);
  long long k1 = k >= 0 ? k % (p - 1) : ((p - 1) - (-k % (p - 1))) % (p - 1);
  Modulo r = pow(k1 / 2);
  if (k1 % 2 == 0)
    return r * r;
  else
    return r * r * n;
}

//(*this)**(-1)
Modulo Modulo::inverse() const {
  long long x, y;
  ext_gcd(n, p, x, y);
  return Modulo(x, p).n;
}

// operator /=
inline Modulo &Modulo::operator/=(const long long rhs) {
  Modulo inv(rhs, p);
  inv = inv.inverse();
  return *this *= inv;
}

inline Modulo &Modulo::operator/=(const Modulo &rhs) {
  (*this) /= rhs.get();
  return *this;
}

// operator +
const Modulo operator+(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) += rhs;
}

const Modulo operator+(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) += rhs;
}

const Modulo operator+(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) += rhs;
}

// operator *
const Modulo operator*(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) *= rhs;
}

const Modulo operator*(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) *= rhs;
}

const Modulo operator*(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) *= rhs;
}

// operator -
const Modulo operator-(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) -= rhs;
}

const Modulo operator-(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) -= rhs;
}

const Modulo operator-(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) -= rhs;
}

// operator /
const Modulo operator/(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) /= rhs;
}

const Modulo operator/(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) /= rhs;
}

const Modulo operator/(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) /= rhs;
}

// very very useful functions
// n**k
Modulo pow(Modulo n, long long k) {
  Modulo tmp = n;
  tmp = tmp.pow(k);
  return tmp;
}

// n!
Modulo fact(long long n, long long p = default_mod,
            long long init_size = 1e+6) {
  static bool is_init = false;
  static std::vector<long long> dat;
  if (!is_init) {
    is_init = true;
    dat.resize(init_size);
    dat[0] = 1;
    for (int i = 1; i < init_size; i++)
      dat[i] = dat[i - 1] * i % p;
  }
  return Modulo(dat[n], p);
}

// 1/n!
Modulo ifact(long long n, long long p = default_mod,
             long long init_size = 1e+6) {
  static bool is_init = false;
  static std::vector<long long> dat;
  if (!is_init) {
    is_init = true;
    dat.resize(init_size);
    dat[0] = 1;
    for (int i = 1; i < init_size; i++)
      dat[i] = (Modulo(dat[i - 1], p) / i).n;
  }
  return Modulo(dat[n], p);
}

// initialize
void initFact(long long init_size, long long p = default_mod) {
  fact(0, p, init_size);
  ifact(0, p, init_size);
}

// nCk
Modulo comb(long long n, long long k, long long p = default_mod) {
  Modulo a = fact(n, p);
  Modulo b = ifact(k, p);
  Modulo c = ifact(n - k, p);
  return a * b * c;
}

// ax + by = d
template <class T> T ext_gcd(T a, T b, T &x, T &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  T d = ext_gcd(b, a % b, x, y);
  T x_ = x;
  x = y;
  y = x_ - a / b * y;
  return d;
}

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

  if ((X + Y) % 3 != 0) {
    cout << 0 << endl;
    return 0;
  }

  ll u = (X + Y) / 3;
  ll v = Y - X;
  if (u < v || (u - v) % 2 != 0) {
    cout << 0 << endl;
    return 0;
  }
  ll p = (u + v) / 2;
  ll q = (u - v) / 2;

  initFact(p + q + 5);
  cout << comb(p + q, p).n << endl;
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;
using ll = long long;
using Pii = pair<int, int>;
using Pll = pair<ll, ll>;
template <class T> using Vvec = vector<vector<T>>;

constexpr long long default_mod = 1e9 + 7;

// element of Z/pZ
class Modulo {
public:
  long long p;
  long long n;

  Modulo(long long n0, long long p0);

  bool operator==(const Modulo rhs) const { return n == rhs.n; }
  Modulo &operator+=(const long long rhs);
  Modulo &operator+=(const Modulo &rhs);
  Modulo &operator*=(const long long rhs);
  Modulo &operator*=(const Modulo &rhs);
  Modulo &operator-=(const long long rhs);
  Modulo &operator-=(const Modulo &rhs);
  Modulo pow(const long long k) const;
  Modulo inverse() const;
  Modulo &operator/=(const long long rhs);
  Modulo &operator/=(const Modulo &rhs);
  long long get() const { return n; };
};

const Modulo operator+(const Modulo &lhs, const Modulo &rhs);
const Modulo operator+(const Modulo &lhs, const long long rhs);
const Modulo operator+(const long long lhs, const Modulo &rhs);
const Modulo operator*(const Modulo &lhs, const Modulo &rhs);
const Modulo operator*(const Modulo &lhs, const long long rhs);
const Modulo operator*(const long long lhs, const Modulo &rhs);

template <class T> T ext_gcd(T a, T b, T &x, T &y);

// constructor
Modulo::Modulo(long long n0, long long p0 = default_mod) : p(p0) {
  n = n0 >= 0 ? n0 % p : (p - (-n0 % p)) % p;
}

// operator +=
inline Modulo &Modulo::operator+=(const long long rhs) {
  long long rhs1 = rhs >= 0 ? rhs % p : (p - (-rhs % p)) % p;
  n = (n + rhs1) % p;
  return *this;
}

inline Modulo &Modulo::operator+=(const Modulo &rhs) {
  (*this) += rhs.n;
  return *this;
}

// operator *=
inline Modulo &Modulo::operator*=(const long long rhs) {
  long long rhs1 = rhs >= 0 ? rhs % p : (p - (-rhs % p)) % p;
  n = (n * rhs1) % p;
  return *this;
}

inline Modulo &Modulo::operator*=(const Modulo &rhs) {
  (*this) *= rhs.n;
  return *this;
}

// operator -=
inline Modulo &Modulo::operator-=(const long long rhs) { return *this += -rhs; }

inline Modulo &Modulo::operator-=(const Modulo &rhs) {
  (*this) -= rhs.get();
  return *this;
}

//(*this)**k
Modulo Modulo::pow(const long long k) const {
  if (k == 0)
    return Modulo(1, p);
  if (k == 1)
    return Modulo(n, p);
  long long k1 = k >= 0 ? k % (p - 1) : ((p - 1) - (-k % (p - 1))) % (p - 1);
  Modulo r = pow(k1 / 2);
  if (k1 % 2 == 0)
    return r * r;
  else
    return r * r * n;
}

//(*this)**(-1)
Modulo Modulo::inverse() const {
  long long x, y;
  ext_gcd(n, p, x, y);
  return Modulo(x, p).n;
}

// operator /=
inline Modulo &Modulo::operator/=(const long long rhs) {
  Modulo inv(rhs, p);
  inv = inv.inverse();
  return *this *= inv;
}

inline Modulo &Modulo::operator/=(const Modulo &rhs) {
  (*this) /= rhs.get();
  return *this;
}

// operator +
const Modulo operator+(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) += rhs;
}

const Modulo operator+(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) += rhs;
}

const Modulo operator+(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) += rhs;
}

// operator *
const Modulo operator*(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) *= rhs;
}

const Modulo operator*(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) *= rhs;
}

const Modulo operator*(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) *= rhs;
}

// operator -
const Modulo operator-(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) -= rhs;
}

const Modulo operator-(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) -= rhs;
}

const Modulo operator-(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) -= rhs;
}

// operator /
const Modulo operator/(const Modulo &lhs, const Modulo &rhs) {
  return Modulo(lhs.get(), lhs.p) /= rhs;
}

const Modulo operator/(const Modulo &lhs, const long long rhs) {
  return Modulo(lhs.get(), lhs.p) /= rhs;
}

const Modulo operator/(const long long lhs, const Modulo &rhs) {
  return Modulo(lhs, rhs.p) /= rhs;
}

// very very useful functions
// n**k
Modulo pow(Modulo n, long long k) {
  Modulo tmp = n;
  tmp = tmp.pow(k);
  return tmp;
}

// n!
Modulo fact(long long n, long long p = default_mod,
            long long init_size = 1e+6) {
  static bool is_init = false;
  static std::vector<long long> dat;
  if (!is_init) {
    is_init = true;
    dat.resize(init_size);
    dat[0] = 1;
    for (int i = 1; i < init_size; i++)
      dat[i] = dat[i - 1] * i % p;
  }
  return Modulo(dat[n], p);
}

// 1/n!
Modulo ifact(long long n, long long p = default_mod,
             long long init_size = 1e+6) {
  static bool is_init = false;
  static std::vector<long long> dat;
  if (!is_init) {
    is_init = true;
    dat.resize(init_size);
    dat[0] = 1;
    for (int i = 1; i < init_size; i++)
      dat[i] = (Modulo(dat[i - 1], p) / i).n;
  }
  return Modulo(dat[n], p);
}

// initialize
void initFact(long long init_size, long long p = default_mod) {
  fact(0, p, init_size);
  ifact(0, p, init_size);
}

// nCk
Modulo comb(long long n, long long k, long long p = default_mod) {
  Modulo a = fact(n, p);
  Modulo b = ifact(k, p);
  Modulo c = ifact(n - k, p);
  return a * b * c;
}

// ax + by = d
template <class T> T ext_gcd(T a, T b, T &x, T &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  T d = ext_gcd(b, a % b, x, y);
  T x_ = x;
  x = y;
  y = x_ - a / b * y;
  return d;
}

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

  if ((X + Y) % 3 != 0) {
    cout << 0 << endl;
    return 0;
  }

  ll u = (X + Y) / 3;
  ll v = Y - X;
  if ((u + v) < 0 || u < v || (u - v) % 2 != 0) {
    cout << 0 << endl;
    return 0;
  }
  ll p = (u + v) / 2;
  ll q = (u - v) / 2;

  initFact(p + q + 5);
  cout << comb(p + q, p).n << endl;
}