Problem p02965 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

#ifdef DEBUG
//~ #define LOCAL_INPUT_FILE
#else
// #define USE_FILE_IO
#endif

#ifdef USE_FILE_IO
#define INPUT_FILE "input.txt"
#define OUTPUT_FILE "output.txt"
#define cin ____cin
#define cout ____cout
ifstream cin(INPUT_FILE);
ofstream cout(OUTPUT_FILE);
#else
#ifdef LOCAL_INPUT_FILE
#define cin ____cin
ifstream cin("input.txt");
#endif
#endif

const int infinity = (int)1e9 + 42;
const int64_t llInfinity = (int64_t)1e18 + 256;
const int mod = 998244353;
const long double eps = 1e-8;

mt19937_64 randGen(system_clock().now().time_since_epoch().count());

inline void raiseError(string errorCode) {
  cerr << "Error : " << errorCode << endl;
  exit(42);
}

const int fMax = 1500 * 1000;
int64_t f[fMax], rf[fMax];

int64_t extGcd(int64_t a, int64_t b, int64_t &x, int64_t &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  int64_t x1, y1;
  int64_t g = extGcd(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return g;
}

inline int64_t inverse(int64_t a, int64_t m = mod) {
  int64_t x, y;
  int64_t g = extGcd(a, m, x, y);
  assert(g == 1);
  return (x % m + m) % m;
}

inline int64_t C(int64_t n, int64_t k) {
  if (k < 0 || k > n) {
    return 0;
  }
  return f[n] * rf[k] % mod * rf[n - k] % mod;
}

inline int64_t cntLim(int64_t n, int64_t sum, int64_t limit) {
  int64_t res = 0;
  for (int i = 0; i <= n; ++i) {
    res +=
        int64_t((i & 1) ? mod - 1 : 1) * C(n, i) % mod * C(n + sum - 1, n - 1);
    res %= mod;
    sum -= limit + 1;
    if (sum < 0) {
      return res;
    }
  }
  return res;
}

signed main() {
#ifndef USE_FILE_IO
  ios_base::sync_with_stdio(false);
#endif

  f[0] = 1;
  for (int i = 1; i < fMax; ++i) {
    f[i] = f[i - 1] * i % mod;
  }
  for (int i = 0; i < fMax; ++i) {
    rf[i] = inverse(f[i]);
  }

  int n, m;
  cin >> n >> m;
  int64_t res = 0;

  // step I: don't have 2*m
  res += [&]() -> int64_t {
    int64_t res = 0;
    for (int i = 0; i <= n && i <= m; ++i) {
      if ((3 * m - i) & 1) {
        continue;
      }
      res += C(n, i) * cntLim(n, (3 * m - i) / 2, m - 1) % mod;
      res %= mod;
    }
    return res;
  }();

  // step II: have 2*m
  res += [&]() -> int64_t {
    int64_t res = 0;
    for (int i = 0; i < n && i <= m; ++i) {
      if ((m - i) & 1) {
        continue;
      }
      res += C(n - 1, i) * cntLim(n - 1, (m - i) / 2, m - 1) % mod;
      res %= mod;
    }
    res *= n;
    res %= mod;
    return res;
  }();

  res %= mod;
  cout << res << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

#ifdef DEBUG
//~ #define LOCAL_INPUT_FILE
#else
// #define USE_FILE_IO
#endif

#ifdef USE_FILE_IO
#define INPUT_FILE "input.txt"
#define OUTPUT_FILE "output.txt"
#define cin ____cin
#define cout ____cout
ifstream cin(INPUT_FILE);
ofstream cout(OUTPUT_FILE);
#else
#ifdef LOCAL_INPUT_FILE
#define cin ____cin
ifstream cin("input.txt");
#endif
#endif

const int infinity = (int)1e9 + 42;
const int64_t llInfinity = (int64_t)1e18 + 256;
const int mod = 998244353;
const long double eps = 1e-8;

mt19937_64 randGen(system_clock().now().time_since_epoch().count());

inline void raiseError(string errorCode) {
  cerr << "Error : " << errorCode << endl;
  exit(42);
}

const int fMax = 1800 * 1000;
int64_t f[fMax], rf[fMax];

int64_t extGcd(int64_t a, int64_t b, int64_t &x, int64_t &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  int64_t x1, y1;
  int64_t g = extGcd(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return g;
}

inline int64_t inverse(int64_t a, int64_t m = mod) {
  int64_t x, y;
  int64_t g = extGcd(a, m, x, y);
  assert(g == 1);
  return (x % m + m) % m;
}

inline int64_t C(int64_t n, int64_t k) {
  if (k < 0 || k > n) {
    return 0;
  }
  return f[n] * rf[k] % mod * rf[n - k] % mod;
}

inline int64_t cntLim(int64_t n, int64_t sum, int64_t limit) {
  int64_t res = 0;
  for (int i = 0; i <= n; ++i) {
    res +=
        int64_t((i & 1) ? mod - 1 : 1) * C(n, i) % mod * C(n + sum - 1, n - 1);
    res %= mod;
    sum -= limit + 1;
    if (sum < 0) {
      return res;
    }
  }
  return res;
}

signed main() {
#ifndef USE_FILE_IO
  ios_base::sync_with_stdio(false);
#endif

  f[0] = 1;
  for (int i = 1; i < fMax; ++i) {
    f[i] = f[i - 1] * i % mod;
  }
  for (int i = 0; i < fMax; ++i) {
    rf[i] = inverse(f[i]);
  }

  int n, m;
  cin >> n >> m;
  int64_t res = 0;

  // step I: don't have 2*m
  res += [&]() -> int64_t {
    int64_t res = 0;
    for (int i = 0; i <= n && i <= m; ++i) {
      if ((3 * m - i) & 1) {
        continue;
      }
      res += C(n, i) * cntLim(n, (3 * m - i) / 2, m - 1) % mod;
      res %= mod;
    }
    return res;
  }();

  // step II: have 2*m
  res += [&]() -> int64_t {
    int64_t res = 0;
    for (int i = 0; i < n && i <= m; ++i) {
      if ((m - i) & 1) {
        continue;
      }
      res += C(n - 1, i) * cntLim(n - 1, (m - i) / 2, m - 1) % mod;
      res %= mod;
    }
    res *= n;
    res %= mod;
    return res;
  }();

  res %= mod;
  cout << res << endl;

  return 0;
}