Problem p03332 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <complex>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <limits>
#include <locale>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <type_traits>
#include <vector>

using namespace std;
#define SAY_YES cout << "YES" << endl;
#define SAY_Yes cout << "Yes" << endl;
#define SAY_NO cout << "NO" << endl;
#define SAY_No cout << "No" << endl;
#define IFYES(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "YES" << endl;                                                     \
  } else {                                                                     \
    cout << "NO" << endl;                                                      \
  }
#define IFYes(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "Yes" << endl;                                                     \
  } else {                                                                     \
    cout << "No" << endl;                                                      \
  }
#define IFyes(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "yes" << endl;                                                     \
  } else {                                                                     \
    cout << "no" << endl;                                                      \
  }
#define DEBUG_OUTPUT_ARRAY(XXX, ONE)                                           \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << "DEBUG: i = " << i << " -> " << XXX[i] << endl;                    \
  }
#define DEBUG_OUTPUT_ARRAY2(XXX, ONE, TWO)                                     \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << "<<< i = " << i << " >>>" << endl;                                 \
    for (int j = 0; j < (TWO); j++) {                                          \
      cout << "DEBUG: j = " << j << " -> " << XXX[i][j] << endl;               \
    }                                                                          \
  }
#define DEBUG_OUTPUT_ARRAY2_BOX(XXX, ONE, TWO)                                 \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << i << "  ";                                                         \
    for (int j = 0; j < (TWO); j++) {                                          \
      cout << XXX[i][j] << " ";                                                \
    }                                                                          \
    cout << endl;                                                              \
  }

typedef pair<long long int, long long int> pll;
typedef pair<long long int, pll> lpll;

const long long int mod = 998244353;
const long long int INF = 1e18;
const long double PI = 3.14159265358979323;

long long int N, P, A, B, C, K, sum[200200] = {}, res = 0;
long long int dp[300300] = {};

// 階乗先に計算
class Kaizyou {
public:
  long long int *kaizyou;
  Kaizyou(){};
  Kaizyou(long long int n, long long int mod) {
    kaizyou = new long long int[n + 1];
    kai(1, n, mod);
    return;
  }

  long long int kai(long long int a, long long int b, long long int mod) {
    long long int tmp = 1;
    kaizyou[0] = 1;
    for (long long int i = a; i <= b; i++) {
      tmp *= i;
      tmp %= mod;

      kaizyou[i] = tmp;
    }
    return tmp;
  }
};

// 累乗(繰り返し2乗法)　aのb乗(mod)を求める。
class Ruizyou {
public:
  long long int rui(long long int a, long long int b, long long mod) {
    int memo[65] = {};
    long long int A[65] = {};
    long long int tmp = 1;
    for (int i = 0; i < 65; i++) {
      memo[i] = b % 2;
      b /= 2;
    }

    A[0] = a;
    A[0] %= mod;

    for (int i = 1; i < 65; i++) {
      A[i] = A[i - 1] * A[i - 1];
      A[i] %= mod;
    }
    for (int i = 0; i < 65; i++) {
      if (memo[i] == 1) {
        tmp *= A[i];
        tmp %= mod;
      }
    }
    tmp %= mod;
    return tmp;
  }
};
// コンビネーション計算
class Combination {
public:
  Kaizyou *Kaizyou_Instance;
  Ruizyou Ruizyou_Instance;
  long long int CombinationMod;
  Combination(long long int n, long long int mod) {
    Kaizyou_Instance = new Kaizyou(n, mod);
    CombinationMod = mod;
  }
  long long int comb(long long int n, long long int r) {
    long long int tmp;
    if (r > n) {
      return 0;
    }
    tmp = (Kaizyou_Instance->kaizyou[n] *
           Ruizyou_Instance.rui(Kaizyou_Instance->kaizyou[r],
                                CombinationMod - 2, CombinationMod)) %
          CombinationMod;
    tmp *= Ruizyou_Instance.rui(Kaizyou_Instance->kaizyou[n - r],
                                CombinationMod - 2, CombinationMod);
    tmp %= CombinationMod;
    if (tmp < 0) {
      tmp = (CombinationMod - tmp) % CombinationMod;
    }
    return tmp;
  }
  // start~endまでのn+iCiの和を出力
  long long int combRange1(long long int n, long long int start,
                           long long int end) {
    if (start != 0)
      return (comb(n + end + 1, end) - comb(n + start, start - 1) +
              3 * CombinationMod) %
             CombinationMod;
    else
      return comb(n + end + 1, end) % CombinationMod;
  }
  // start1~end1のiとstart2~end2のjまでのi+jCiの和を出力
  long long int combRange2(long long int start1, long long int end1,
                           long long int start2, long long int end2) {
    return (comb(end1 + end2 + 2, end1 + 1) - comb(end1 + start2 + 1, start2) -
            comb(end2 + start1 + 1, start1) + comb(start1 + start2, start1) +
            5 * CombinationMod) %
           CombinationMod;
  }

  long long int Lucas(long long int n, long long int r) {
    long long int ret = 1;
    while (r != 0) {
      ret *= comb(n % CombinationMod, r % CombinationMod);
      n /= CombinationMod;
      r /= CombinationMod;
    }
    return ret % CombinationMod;
  }
};

int main() {
  cout << fixed << setprecision(18);
  cin >> N >> A >> B >> K;
  Combination Com(N, mod);
  for (long long int a = 0; a <= N; a++) {
    long long int nokori = K - a * A;
    if (nokori % B != 0 || nokori / B > N) {
      continue;
    }
    long long int b = nokori / B;
    res += Com.comb(N, a) * Com.comb(N, b);
    res %= mod;
  }
  cout << res << endl;
}


Fixed submission:
#include <algorithm>
#include <complex>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <limits>
#include <locale>
#include <map>
#include <math.h>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <type_traits>
#include <vector>

using namespace std;
#define SAY_YES cout << "YES" << endl;
#define SAY_Yes cout << "Yes" << endl;
#define SAY_NO cout << "NO" << endl;
#define SAY_No cout << "No" << endl;
#define IFYES(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "YES" << endl;                                                     \
  } else {                                                                     \
    cout << "NO" << endl;                                                      \
  }
#define IFYes(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "Yes" << endl;                                                     \
  } else {                                                                     \
    cout << "No" << endl;                                                      \
  }
#define IFyes(TRUE_OR_FALSE)                                                   \
  if (TRUE_OR_FALSE) {                                                         \
    cout << "yes" << endl;                                                     \
  } else {                                                                     \
    cout << "no" << endl;                                                      \
  }
#define DEBUG_OUTPUT_ARRAY(XXX, ONE)                                           \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << "DEBUG: i = " << i << " -> " << XXX[i] << endl;                    \
  }
#define DEBUG_OUTPUT_ARRAY2(XXX, ONE, TWO)                                     \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << "<<< i = " << i << " >>>" << endl;                                 \
    for (int j = 0; j < (TWO); j++) {                                          \
      cout << "DEBUG: j = " << j << " -> " << XXX[i][j] << endl;               \
    }                                                                          \
  }
#define DEBUG_OUTPUT_ARRAY2_BOX(XXX, ONE, TWO)                                 \
  for (int i = 0; i < (ONE); i++) {                                            \
    cout << i << "  ";                                                         \
    for (int j = 0; j < (TWO); j++) {                                          \
      cout << XXX[i][j] << " ";                                                \
    }                                                                          \
    cout << endl;                                                              \
  }

typedef pair<long long int, long long int> pll;
typedef pair<long long int, pll> lpll;

const long long int mod = 998244353;
const long long int INF = 1e18;
const long double PI = 3.14159265358979323;

long long int N, P, A, B, C, K, sum[200200] = {}, res = 0;
long long int dp[300300] = {};

// 階乗先に計算
class Kaizyou {
public:
  long long int *kaizyou;
  Kaizyou(){};
  Kaizyou(long long int n, long long int mod) {
    kaizyou = new long long int[n + 1];
    kai(1, n, mod);
    return;
  }

  long long int kai(long long int a, long long int b, long long int mod) {
    long long int tmp = 1;
    kaizyou[0] = 1;
    for (long long int i = a; i <= b; i++) {
      tmp *= i;
      tmp %= mod;

      kaizyou[i] = tmp;
    }
    return tmp;
  }
};

// 累乗(繰り返し2乗法)　aのb乗(mod)を求める。
class Ruizyou {
public:
  long long int rui(long long int a, long long int b, long long mod) {
    int memo[65] = {};
    long long int A[65] = {};
    long long int tmp = 1;
    for (int i = 0; i < 65; i++) {
      memo[i] = b % 2;
      b /= 2;
    }

    A[0] = a;
    A[0] %= mod;

    for (int i = 1; i < 65; i++) {
      A[i] = A[i - 1] * A[i - 1];
      A[i] %= mod;
    }
    for (int i = 0; i < 65; i++) {
      if (memo[i] == 1) {
        tmp *= A[i];
        tmp %= mod;
      }
    }
    tmp %= mod;
    return tmp;
  }
};
// コンビネーション計算
class Combination {
public:
  Kaizyou *Kaizyou_Instance;
  Ruizyou Ruizyou_Instance;
  long long int CombinationMod;
  Combination(long long int n, long long int mod) {
    Kaizyou_Instance = new Kaizyou(n, mod);
    CombinationMod = mod;
  }
  long long int comb(long long int n, long long int r) {
    long long int tmp;
    if (r > n) {
      return 0;
    }
    tmp = (Kaizyou_Instance->kaizyou[n] *
           Ruizyou_Instance.rui(Kaizyou_Instance->kaizyou[r],
                                CombinationMod - 2, CombinationMod)) %
          CombinationMod;
    tmp *= Ruizyou_Instance.rui(Kaizyou_Instance->kaizyou[n - r],
                                CombinationMod - 2, CombinationMod);
    tmp %= CombinationMod;
    if (tmp < 0) {
      tmp = (CombinationMod - tmp) % CombinationMod;
    }
    return tmp;
  }
  // start~endまでのn+iCiの和を出力
  long long int combRange1(long long int n, long long int start,
                           long long int end) {
    if (start != 0)
      return (comb(n + end + 1, end) - comb(n + start, start - 1) +
              3 * CombinationMod) %
             CombinationMod;
    else
      return comb(n + end + 1, end) % CombinationMod;
  }
  // start1~end1のiとstart2~end2のjまでのi+jCiの和を出力
  long long int combRange2(long long int start1, long long int end1,
                           long long int start2, long long int end2) {
    return (comb(end1 + end2 + 2, end1 + 1) - comb(end1 + start2 + 1, start2) -
            comb(end2 + start1 + 1, start1) + comb(start1 + start2, start1) +
            5 * CombinationMod) %
           CombinationMod;
  }

  long long int Lucas(long long int n, long long int r) {
    long long int ret = 1;
    while (r != 0) {
      ret *= comb(n % CombinationMod, r % CombinationMod);
      n /= CombinationMod;
      r /= CombinationMod;
    }
    return ret % CombinationMod;
  }
};

int main() {
  cout << fixed << setprecision(18);
  cin >> N >> A >> B >> K;
  Combination Com(N, mod);
  for (long long int a = 0; a <= N; a++) {
    long long int nokori = K - a * A;
    if (nokori % B != 0 || nokori / B > N || nokori / B < 0) {
      continue;
    }
    long long int b = nokori / B;
    res += Com.comb(N, a) * Com.comb(N, b);
    res %= mod;
  }
  cout << res << endl;
}