Problem p03332 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <utility>
#include <vector>

using namespace std;

static const double EPS = 1e-9;
template <class T> bool INRANGE(T x, T a, T b) { return a <= x && x <= b; }
template <class T> void amin(T &a, T v) {
  if (a > v)
    a = v;
}
template <class T> void amax(T &a, T v) {
  if (a < v)
    a = v;
}
int ROUND(double x) { return (int)(x + 0.5); }
bool ISINT(double x) { return fabs(ROUND(x) - x) <= EPS; }
bool ISEQUAL(double x, double y) {
  return fabs(x - y) <= EPS * max(1.0, max(fabs(x), fabs(y)));
}
double SQSUM(double x, double y) { return x * x + y * y; }
#define PI (acos(-1))
#define ARRAY_NUM(a) (sizeof(a) / sizeof(a[0]))
#define NG (-1)
#define BIG ((int)1e9 + 10)
#define BIGLL ((ll)4e18)
#define SZ(a) ((int)(a).size())
#define SQ(a) ((a) * (a))
typedef unsigned long long ull;
typedef long long ll;

enum { NUM_FACTORIAL = 1012345 };
ll f[NUM_FACTORIAL];
ll f_inv[NUM_FACTORIAL];
ll MOD = 998244353;

// MODが素数以外でも使えるバージョン。階乗の逆元を求める。
ll extgcd(ll a, ll b, ll &x, ll &y) {
  ll d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}

// 逆元を求める
ll mod_inverse(ll a, ll m) {
  ll x, y;
  extgcd(a, m, x, y);
  return (m + x % m) % m;
}

void mod_factorial_init() {
  f[0] = 1;
  for (int i = 1; i < NUM_FACTORIAL; ++i) {
    f[i] = f[i - 1] * i;
    f[i] %= MOD;
  }

  for (int i = 0; i < NUM_FACTORIAL; ++i) {
    f_inv[i] = mod_inverse(f[i], MOD);
  }
}

// 組み合わせを求める。事前計算O(n)で、0～nまでと範囲も広いので、MODつきならパスカルの三角形よりも良い。最有力。
ll mod_comb(ll n, ll k) {
  if (k > n) {
    return 0;
  }

  return ((f[n] * f_inv[k]) % MOD * f_inv[n - k]) % MOD;
}

int main() {
  mod_factorial_init();

  ll N, A, B, K;
  cin >> N >> A >> B >> K;

  ll ans = 0;

  for (ll r = 0; r <= N; r++) {
    if ((K - r * A) % B == 0) {
      ll b = (K - r * A) / B;

      ll tmp = (mod_comb(N, r) * mod_comb(N, b)) % MOD;
      ans += tmp;
      ans %= MOD;
    }
  }

  cout << ans << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <utility>
#include <vector>

using namespace std;

static const double EPS = 1e-9;
template <class T> bool INRANGE(T x, T a, T b) { return a <= x && x <= b; }
template <class T> void amin(T &a, T v) {
  if (a > v)
    a = v;
}
template <class T> void amax(T &a, T v) {
  if (a < v)
    a = v;
}
int ROUND(double x) { return (int)(x + 0.5); }
bool ISINT(double x) { return fabs(ROUND(x) - x) <= EPS; }
bool ISEQUAL(double x, double y) {
  return fabs(x - y) <= EPS * max(1.0, max(fabs(x), fabs(y)));
}
double SQSUM(double x, double y) { return x * x + y * y; }
#define PI (acos(-1))
#define ARRAY_NUM(a) (sizeof(a) / sizeof(a[0]))
#define NG (-1)
#define BIG ((int)1e9 + 10)
#define BIGLL ((ll)4e18)
#define SZ(a) ((int)(a).size())
#define SQ(a) ((a) * (a))
typedef unsigned long long ull;
typedef long long ll;

enum { NUM_FACTORIAL = 1012345 };
ll f[NUM_FACTORIAL];
ll f_inv[NUM_FACTORIAL];
ll MOD = 998244353;

// MODが素数以外でも使えるバージョン。階乗の逆元を求める。
ll extgcd(ll a, ll b, ll &x, ll &y) {
  ll d = a;
  if (b != 0) {
    d = extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
  return d;
}

// 逆元を求める
ll mod_inverse(ll a, ll m) {
  ll x, y;
  extgcd(a, m, x, y);
  return (m + x % m) % m;
}

void mod_factorial_init() {
  f[0] = 1;
  for (int i = 1; i < NUM_FACTORIAL; ++i) {
    f[i] = f[i - 1] * i;
    f[i] %= MOD;
  }

  for (int i = 0; i < NUM_FACTORIAL; ++i) {
    f_inv[i] = mod_inverse(f[i], MOD);
  }
}

// 組み合わせを求める。事前計算O(n)で、0～nまでと範囲も広いので、MODつきならパスカルの三角形よりも良い。最有力。
ll mod_comb(ll n, ll k) {
  if (k > n) {
    return 0;
  }

  return ((f[n] * f_inv[k]) % MOD * f_inv[n - k]) % MOD;
}

int main() {
  mod_factorial_init();

  ll N, A, B, K;
  cin >> N >> A >> B >> K;

  ll ans = 0;

  for (ll r = 0; r <= N; r++) {
    if ((K - r * A) % B == 0) {
      ll b = (K - r * A) / B;
      if (b >= 0) {
        ll tmp = (mod_comb(N, r) * mod_comb(N, b)) % MOD;
        ans += tmp;
        ans %= MOD;
      }
    }
  }

  cout << ans << endl;

  return 0;
}