Problem p02662 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define P pair<int, int>
using ll = int64_t;
using namespace std;
#define ketasuu(n) fixed << setprecision(n)
#define btoe(p) p.begin(), p.end()
#define etob(p) p.rbegin(), p.rend()

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define P pair<int, int>
using ll = int64_t;
using namespace std;
#define ketasuu(n) fixed << setprecision(n)
#define btoe(p) p.begin(), p.end()
#define etob(p) p.rbegin(), p.rend()

// library mod int
template <int mod> struct modint {
  ll x;

  // constructor
  modint(ll x = 0) : x((x % mod + mod) % mod) {}

  // unary operator
  modint operator-() const { return modint(mod - x); }
  modint inv() const { return this->pow(mod - 2); }

  // compound assignment
  modint &operator+=(const modint &a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  modint &operator-=(const modint &a) {
    if ((x -= a.x) < 0)
      x += mod;
    return *this;
  }
  modint &operator*=(const modint &a) {
    (x *= a.x) %= mod;
    return *this;
  }
  modint &operator/=(const modint &a) { return *this *= a.inv(); }

  // arithmetic
  //  なぜmodintの後ろに＆を書いたり書かなかったりしてるかの理解ができていない
  // おそらく＆をつけるとポインタで参照しているのでもとの値を書き換えることができる
  // ＆をつけないとコピーを作ってからそれに対して計算するので、もとの値は変更されない
  modint operator-(const modint &a) const { return modint(*this) -= a; }
  modint operator+(const modint &a) const { return modint(*this) += a; }
  modint operator*(const modint &a) const { return modint(*this) *= a; }
  modint operator/(const modint &a) const { return modint(*this) /= a; }
  // n should not be smaller than 0.
  modint pow(ll n) const {
    auto x = modint(1);
    auto m = *this;
    while (n > 0) {
      if (n & 1)
        x *= m;
      n >>= 1;
      m *= m;
    }
    return x;
  }

  // compare
  bool operator==(const modint &a) const { return x == a.x; }
  bool operator!=(const modint &a) const { return x != a.x; }

  // I/O
  friend istream &operator>>(istream &is, modint &a) noexcept {
    return is >> a.x;
  }
  friend ostream &operator<<(ostream &os, const modint &a) noexcept {
    return os << a.x;
  }
};

// modの調整
constexpr int mod = 998244353;
using mint = modint<mod>;

//////////////////////////////////////////////////////////////////////
// mint power
mint mpow(mint a, mint b) {
  auto x = mint(1), m = a;
  auto n = b.x;
  while (n > 0) {
    if (n & 1)
      x *= m;
    n >>= 1;
    m *= m;
  }
  return x;
}

// combination
vector<mint> mintcombvector;
int startmintcomb(int n) {
  mintcombvector.push_back(0);
  mintcombvector.push_back(1);
  rep(i, n) mintcombvector.push_back(mintcombvector[i + 1] * (i + 2));
  return 0;
}
mint comb(mint a, mint b) {
  if (a.x < b.x || a.x <= 0 || b.x < 0)
    return mint(0);
  if (b.x == 0)
    return mint(1);
  if (a == b)
    return mint(1);
  return mintcombvector[a.x] * (mintcombvector[b.x].inv()) *
         (mintcombvector[a.x - b.x].inv());
}
// combinationを使いたいときは　startmintcomb(n=代入したい数の最大値);
// を始めに打つこと

int main() {
  int n, s;
  cin >> n >> s;
  vector<int> p(n);
  rep(i, n) cin >> p[i];
  vector<vector<mint>> dp(n + 5, vector<mint>(s + 5, 0));
  dp[0][0] = mpow(2, n);
  rep(i, n) {
    rep(j, s + 1) {
      if (dp[i][j] != 0) {
        dp[i + 1][j] += dp[i][j];
        if (j + p[i] <= s) {
          mint a(2);
          a = dp[i][j] / a;
          dp[i + 1][j + p[i]] += a;
        }
      }
    }
  }
  cout << dp[n][s] << endl;
  return 0;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define P pair<int, int>
using ll = int64_t;
using namespace std;
#define ketasuu(n) fixed << setprecision(n)
#define btoe(p) p.begin(), p.end()
#define etob(p) p.rbegin(), p.rend()

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define P pair<int, int>
using ll = int64_t;
using namespace std;
#define ketasuu(n) fixed << setprecision(n)
#define btoe(p) p.begin(), p.end()
#define etob(p) p.rbegin(), p.rend()

// library mod int
template <int mod> struct modint {
  ll x;

  // constructor
  modint(ll x = 0) : x((x % mod + mod) % mod) {}

  // unary operator
  modint operator-() const { return modint(mod - x); }
  modint inv() const { return this->pow(mod - 2); }

  // compound assignment
  modint &operator+=(const modint &a) {
    if ((x += a.x) >= mod)
      x -= mod;
    return *this;
  }
  modint &operator-=(const modint &a) {
    if ((x -= a.x) < 0)
      x += mod;
    return *this;
  }
  modint &operator*=(const modint &a) {
    (x *= a.x) %= mod;
    return *this;
  }
  modint &operator/=(const modint &a) { return *this *= a.inv(); }

  // arithmetic
  //  なぜmodintの後ろに＆を書いたり書かなかったりしてるかの理解ができていない
  // おそらく＆をつけるとポインタで参照しているのでもとの値を書き換えることができる
  // ＆をつけないとコピーを作ってからそれに対して計算するので、もとの値は変更されない
  modint operator-(const modint &a) const { return modint(*this) -= a; }
  modint operator+(const modint &a) const { return modint(*this) += a; }
  modint operator*(const modint &a) const { return modint(*this) *= a; }
  modint operator/(const modint &a) const { return modint(*this) /= a; }
  // n should not be smaller than 0.
  modint pow(ll n) const {
    auto x = modint(1);
    auto m = *this;
    while (n > 0) {
      if (n & 1)
        x *= m;
      n >>= 1;
      m *= m;
    }
    return x;
  }

  // compare
  bool operator==(const modint &a) const { return x == a.x; }
  bool operator!=(const modint &a) const { return x != a.x; }

  // I/O
  friend istream &operator>>(istream &is, modint &a) noexcept {
    return is >> a.x;
  }
  friend ostream &operator<<(ostream &os, const modint &a) noexcept {
    return os << a.x;
  }
};

// modの調整
constexpr int mod = 998244353;
using mint = modint<mod>;

//////////////////////////////////////////////////////////////////////
// mint power
mint mpow(mint a, mint b) {
  auto x = mint(1), m = a;
  auto n = b.x;
  while (n > 0) {
    if (n & 1)
      x *= m;
    n >>= 1;
    m *= m;
  }
  return x;
}

// combination
vector<mint> mintcombvector;
int startmintcomb(int n) {
  mintcombvector.push_back(0);
  mintcombvector.push_back(1);
  rep(i, n) mintcombvector.push_back(mintcombvector[i + 1] * (i + 2));
  return 0;
}
mint comb(mint a, mint b) {
  if (a.x < b.x || a.x <= 0 || b.x < 0)
    return mint(0);
  if (b.x == 0)
    return mint(1);
  if (a == b)
    return mint(1);
  return mintcombvector[a.x] * (mintcombvector[b.x].inv()) *
         (mintcombvector[a.x - b.x].inv());
}
// combinationを使いたいときは　startmintcomb(n=代入したい数の最大値);
// を始めに打つこと

int main() {
  int n, s;
  cin >> n >> s;
  vector<int> p(n);
  rep(i, n) cin >> p[i];
  vector<vector<mint>> dp(s + 5, vector<mint>(n + 5, 0));
  dp[0][0] = mpow(2, n);
  rep(i, n) {
    rep(j, s + 1) {
      if (dp[i][j] != 0) {
        dp[i + 1][j] += dp[i][j];
        if (j + p[i] <= s) {
          dp[i + 1][j + p[i]] += dp[i][j] / 2;
        }
      }
    }
  }
  cout << dp[n][s] << endl;
  return 0;
}