Problem p03332 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;
using ll = long long int;

template <typename T> T powint(T a, ll n) {
  T ret = 1;
  while (n > 0) {
    if (n & 1)
      ret *= a;
    a *= a;
    n >>= 1;
  }
  return ret;
}

template <ll mod> class ModInt {
private:
  ll num;

public:
  ModInt(){};
  ModInt(ll n) { num = n % mod; }
  ModInt inv() const { return powint(*this, mod - 2); }
  explicit operator ll() const { return num; }

  ModInt &operator+=(const ModInt &a) {
    num += a.num;
    if (num >= mod)
      num -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &a) {
    if (num < a.num)
      num += mod;
    num -= a.num;
    return *this;
  }
  ModInt &operator*=(const ModInt &a) {
    num = num * a.num % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &a) { return *this *= a.inv(); }
  friend ModInt operator+(const ModInt &a, const ModInt &b) {
    return ModInt(a) += b;
  }
  friend ModInt operator-(const ModInt &a, const ModInt &b) {
    return ModInt(a) -= b;
  }
  friend ModInt operator*(const ModInt &a, const ModInt &b) {
    return ModInt(a) *= b;
  }
  friend ModInt operator/(const ModInt &a, const ModInt &b) {
    return ModInt(a) /= b;
  }

  friend ostream &operator<<(ostream &os, const ModInt &a) {
    return os << a.num;
  }
  friend istream &operator>>(istream &is, ModInt &a) {
    ll tmp;
    is >> tmp;
    a.num = tmp % mod;
    return is;
  }
};
using mint = ModInt<998244353>;

vector<mint> fact, factinv;
static void fact_reserve(int n) {
  fact.resize(n + 1);
  factinv.resize(n + 1);
  fact[0] = 1;
  for (int i = 1; i <= n; ++i) {
    fact[i] = (ll)fact[i - 1] * i;
  }
  factinv[n] = fact[n].inv();
  for (int i = n; i >= 1; --i) {
    factinv[i - 1] = (ll)factinv[i] * i;
  }
}

mint P(int n, int k) { return fact[n] * factinv[n - k]; }
mint C(int n, int k) { return fact[n] * factinv[n - k] * factinv[k]; }
mint H(int n, int k) { return C(n + k - 1, k); }

ll extgcd(ll a, ll b, ll &x, ll &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  ll d = extgcd(b, a % b, y, x);
  y -= a / b * x;
  return d;
}

int main() {
  ll n, a, b, k;
  cin >> n >> a >> b >> k;

  if (k == 0) {
    cout << 1 << endl;
    return 0;
  }

  ll x, y;
  ll g = extgcd(a, b, x, y);
  x *= k / g;
  y *= k / g;

  if (k % g != 0) {
    cout << 0 << endl;
    return 0;
  }

  fact_reserve(n);

  mint ans = 0;
  ll c = b / g, d = -a / g;
  for (ll m = -x / c; c * m + x <= n; ++m) {
    ll ac = c * m + x, bc = d * m + y;
    if (bc < 0 || bc > n)
      continue;
    ans += C(n, ac) * C(n, bc);
  }

  cout << ans << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;
using ll = long long int;

template <typename T> T powint(T a, ll n) {
  T ret = 1;
  while (n > 0) {
    if (n & 1)
      ret *= a;
    a *= a;
    n >>= 1;
  }
  return ret;
}

template <ll mod> class ModInt {
private:
  ll num;

public:
  ModInt(){};
  ModInt(ll n) { num = n % mod; }
  ModInt inv() const { return powint(*this, mod - 2); }
  explicit operator ll() const { return num; }

  ModInt &operator+=(const ModInt &a) {
    num += a.num;
    if (num >= mod)
      num -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &a) {
    if (num < a.num)
      num += mod;
    num -= a.num;
    return *this;
  }
  ModInt &operator*=(const ModInt &a) {
    num = num * a.num % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &a) { return *this *= a.inv(); }
  friend ModInt operator+(const ModInt &a, const ModInt &b) {
    return ModInt(a) += b;
  }
  friend ModInt operator-(const ModInt &a, const ModInt &b) {
    return ModInt(a) -= b;
  }
  friend ModInt operator*(const ModInt &a, const ModInt &b) {
    return ModInt(a) *= b;
  }
  friend ModInt operator/(const ModInt &a, const ModInt &b) {
    return ModInt(a) /= b;
  }

  friend ostream &operator<<(ostream &os, const ModInt &a) {
    return os << a.num;
  }
  friend istream &operator>>(istream &is, ModInt &a) {
    ll tmp;
    is >> tmp;
    a.num = tmp % mod;
    return is;
  }
};
using mint = ModInt<998244353>;

vector<mint> fact, factinv;
static void fact_reserve(int n) {
  fact.resize(n + 1);
  factinv.resize(n + 1);
  fact[0] = 1;
  for (int i = 1; i <= n; ++i) {
    fact[i] = (ll)fact[i - 1] * i;
  }
  factinv[n] = fact[n].inv();
  for (int i = n; i >= 1; --i) {
    factinv[i - 1] = (ll)factinv[i] * i;
  }
}

mint P(int n, int k) { return fact[n] * factinv[n - k]; }
mint C(int n, int k) { return fact[n] * factinv[n - k] * factinv[k]; }
mint H(int n, int k) { return C(n + k - 1, k); }

ll extgcd(ll a, ll b, ll &x, ll &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  ll d = extgcd(b, a % b, y, x);
  y -= a / b * x;
  return d;
}

int main() {
  ll n, a, b, k;
  cin >> n >> a >> b >> k;

  if (k == 0) {
    cout << 1 << endl;
    return 0;
  }

  ll x, y;
  ll g = extgcd(a, b, x, y);
  x *= k / g;
  y *= k / g;

  if (k % g != 0) {
    cout << 0 << endl;
    return 0;
  }

  fact_reserve(n);

  mint ans = 0;
  ll c = b / g, d = -a / g;
  for (ll m = ceil((double)-x / c); c * m + x <= n; ++m) {
    ll ac = c * m + x, bc = d * m + y;
    if (bc < 0 || bc > n)
      continue;
    ans += C(n, ac) * C(n, bc);
  }

  cout << ans << endl;

  return 0;
}