Problem p02965 (C++)

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

using namespace std;

template <class T> inline T updmax(T &a, T b) { return a = max(a, b); }
template <class T> inline T updmin(T &a, T b) { return a = min(a, b); }

template <unsigned long long mod> class modint {
public:
  unsigned long long v;
  modint(const long long x = 0) : v(x % mod) {}
  modint operator+(const modint rhs) { return modint(*this) += rhs; }
  modint operator-(const modint rhs) { return modint(*this) -= rhs; }
  modint operator*(const modint rhs) { return modint(*this) *= rhs; }
  modint operator/(const modint rhs) { return modint(*this) /= rhs; }
  modint operator-() { return modint(mod - this->v); }
  modint &operator+=(const modint rhs) {
    v += rhs.v;
    if (v >= mod)
      v -= mod;
    return *this;
  }
  modint &operator-=(const modint rhs) {
    if (v < rhs.v)
      v += mod;
    v -= rhs.v;
    return *this;
  }
  modint &operator*=(const modint rhs) {
    v = v * rhs.v % mod;
    return *this;
  }
  modint inverse(modint a) {
    unsigned long long exp = mod - 2;
    modint ret(1ULL);
    while (exp) {
      if (exp % 2) {
        ret *= a;
      }
      a *= a;
      exp >>= 1;
    }
    return ret;
  }
  modint &operator/=(modint rhs) {
    (*this) *= inverse(rhs);
    return *this;
  }
  friend ostream &operator<<(ostream &os, modint u) {
    os << u.v;
    return (os);
  }
  friend istream &operator>>(istream &is, modint &u) {
    is >> u.v;
    return (is);
  }
};

const int MOD = 998244353;
using mint = modint<MOD>;

const int MAX = 1000005;
mint fact[MAX], invfact[MAX], inv[MAX];

void facinit() {
  fact[0] = fact[1] = 1;
  invfact[0] = invfact[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fact[i] = fact[i - 1] * i;
    inv[i] = -inv[MOD % i] * (MOD / i);
    invfact[i] = invfact[i - 1] * inv[i];
  }
}

mint nPr(int n, int r) { return fact[n] * invfact[n - r]; }

mint nCr(int n, int r) {
  if (n < 0 || r < 0 || n < r)
    return mint{0};
  return fact[n] * invfact[r] * invfact[n - r];
}

mint nHr(int n, int r) {
  if (n == 0 && r == 0)
    return mint{1};
  return nCr(n + r - 1, r);
}

class Solution {
public:
  void solve() {
    int n, m;
    cin >> n >> m;
    mint ok{0}, ng{0};
    facinit();
    for (int odd = m % 2; odd <= min(n, m); odd += 2) {
      ok += nCr(n, odd) * nHr(n, (3 * m - odd) / 2);
      ng += nCr(n, odd) * (nHr(n, (m - odd) / 2) * odd +
                           nHr(n, (m - odd - 2) / 2) * (n - odd));
    }

    cout << ok - ng << endl;
    return;
  };
};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  Solution solution;
  solution.solve();
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

template <class T> inline T updmax(T &a, T b) { return a = max(a, b); }
template <class T> inline T updmin(T &a, T b) { return a = min(a, b); }

template <unsigned long long mod> class modint {
public:
  unsigned long long v;
  modint(const long long x = 0) : v(x % mod) {}
  modint operator+(const modint rhs) { return modint(*this) += rhs; }
  modint operator-(const modint rhs) { return modint(*this) -= rhs; }
  modint operator*(const modint rhs) { return modint(*this) *= rhs; }
  modint operator/(const modint rhs) { return modint(*this) /= rhs; }
  modint operator-() { return modint(mod - this->v); }
  modint &operator+=(const modint rhs) {
    v += rhs.v;
    if (v >= mod)
      v -= mod;
    return *this;
  }
  modint &operator-=(const modint rhs) {
    if (v < rhs.v)
      v += mod;
    v -= rhs.v;
    return *this;
  }
  modint &operator*=(const modint rhs) {
    v = v * rhs.v % mod;
    return *this;
  }
  modint inverse(modint a) {
    unsigned long long exp = mod - 2;
    modint ret(1ULL);
    while (exp) {
      if (exp % 2) {
        ret *= a;
      }
      a *= a;
      exp >>= 1;
    }
    return ret;
  }
  modint &operator/=(modint rhs) {
    (*this) *= inverse(rhs);
    return *this;
  }
  friend ostream &operator<<(ostream &os, modint u) {
    os << u.v;
    return (os);
  }
  friend istream &operator>>(istream &is, modint &u) {
    is >> u.v;
    return (is);
  }
};

const int MOD = 998244353;
using mint = modint<MOD>;

const int MAX = 3000005;
mint fact[MAX], invfact[MAX], inv[MAX];

void facinit() {
  fact[0] = fact[1] = 1;
  invfact[0] = invfact[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fact[i] = fact[i - 1] * i;
    inv[i] = -inv[MOD % i] * (MOD / i);
    invfact[i] = invfact[i - 1] * inv[i];
  }
}

mint nPr(int n, int r) { return fact[n] * invfact[n - r]; }

mint nCr(int n, int r) {
  if (n < 0 || r < 0 || n < r)
    return mint{0};
  return fact[n] * invfact[r] * invfact[n - r];
}

mint nHr(int n, int r) {
  if (n == 0 && r == 0)
    return mint{1};
  return nCr(n + r - 1, r);
}

class Solution {
public:
  void solve() {
    int n, m;
    cin >> n >> m;
    mint ok{0}, ng{0};
    facinit();
    for (int odd = m % 2; odd <= min(n, m); odd += 2) {
      ok += nCr(n, odd) * nHr(n, (3 * m - odd) / 2);
      ng += nCr(n, odd) * (nHr(n, (m - odd) / 2) * odd +
                           nHr(n, (m - odd - 2) / 2) * (n - odd));
    }

    cout << ok - ng << endl;
    return;
  };
};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  Solution solution;
  solution.solve();
  return 0;
}