Problem p03134 (C++)

Buggy submission (status: Runtime Error):
// #pragma GCC optimize ("-O3","unroll-loops")
#include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i = 0; i < n; ++i)
#define REPR(i, n) for (int i = n - 1; i >= 0; --i)
#define FOR(i, m, n) for (int i = m; i < n; ++i)
#define FORR(i, m, n) for (int i = m - 1; i >= n; --i)
#define SORT(v, n) sort(v, v + n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v, n) reverse(v, v + n);
#define VREVERSE(v) reverse(v.begin(), v.end())
#define ll long long
#define pb(a) push_back
#define print(x) cout << (x) << '\n'
#define pe(x) cout << (x) << " "
#define DEBUG(x) cout << #x << ": " << x << endl
#define lb(v, n) lower_bound(v.begin(), v.end(), n)
#define ub(v, n) upper_bound(v.begin(), v.end(), n)
#define int long long
#define all(x) (x).begin(), (x).end()
#define print_space(v)                                                         \
  REP(i, v.size()) cout << v[i] << ((i == v.size() - 1) ? "\n" : " ")
#define move(x) ans.push_back(x), c[x]--, now = x;

template <typename T1, typename T2> inline void chmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
}
template <typename T1, typename T2> inline void chmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
}
typedef pair<int, int> P;
const int MOD = 998244353;
const int MAX = 200020;
const double pi = acos(-1);
const double EPS = 1e-12;
const ll INF = 2e18;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
    finv[i] = finv[i - 1] * inv[i] % MOD;
  }
}

// 二項係数計算
long long COM(int n, int k) {
  if (n < k)
    return 0;
  if (n < 0 || k < 0)
    return 0;
  return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
ll add(ll x, ll y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}
ll sub(ll x, ll y) {
  x -= y;
  if (x < 0)
    return x + MOD;
  return x;
}
ll mult(ll x, ll y) { return (x * y) % MOD; }
ll bin_pow(ll x, ll p) {
  if (p == 0)
    return 1;
  if (p & 1)
    return mult(x, bin_pow(x, p - 1));
  return bin_pow(mult(x, x), p / 2);
}

int dp[2020][2020];
int cumR[2020];
int A[2020], B[2020];
int sumR, sumB;
void solve() {
  string S;
  cin >> S;
  int N = S.size();
  COMinit();
  REP(i, N) {
    int num = S[i] - '0';
    A[i] += num;
    B[i] += 2 - num;
    cumR[i + 1] += cumR[i] + A[i];
    sumR += A[i];
    sumB += B[i];
  }
  dp[0][0] = 1;
  REP(i, N) {
    REP(r, N + 1) {
      if (r > 0 && cumR[i + 1] >= r)
        dp[i + 1][r] += dp[i][r - 1];
      int cumB = (i + 1) * 2 - cumR[i + 1];
      if (cumB >= i + 1 - r)
        dp[i + 1][r] += dp[i][r];
      assert(dp[i + 1][r] >= 0);
      // pe(i+1);pe(r);print(dp[i+1][r]);
    }
  }
  ll ans = 0;

  REP(r, N + 1) {
    ll res = mult(dp[N][r], fac[N]);
    res = mult(res, mult(finv[sumR - r], finv[sumB - (N - r)]));
    ans = add(ans, res);
  }
  print(ans);
}

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  solve();
}

Fixed submission:
// #pragma GCC optimize ("-O3","unroll-loops")
#include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i = 0; i < n; ++i)
#define REPR(i, n) for (int i = n - 1; i >= 0; --i)
#define FOR(i, m, n) for (int i = m; i < n; ++i)
#define FORR(i, m, n) for (int i = m - 1; i >= n; --i)
#define SORT(v, n) sort(v, v + n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v, n) reverse(v, v + n);
#define VREVERSE(v) reverse(v.begin(), v.end())
#define ll long long
#define pb(a) push_back
#define print(x) cout << (x) << '\n'
#define pe(x) cout << (x) << " "
#define DEBUG(x) cout << #x << ": " << x << endl
#define lb(v, n) lower_bound(v.begin(), v.end(), n)
#define ub(v, n) upper_bound(v.begin(), v.end(), n)
#define int long long
#define all(x) (x).begin(), (x).end()
#define print_space(v)                                                         \
  REP(i, v.size()) cout << v[i] << ((i == v.size() - 1) ? "\n" : " ")
#define move(x) ans.push_back(x), c[x]--, now = x;

template <typename T1, typename T2> inline void chmin(T1 &a, T2 b) {
  if (a > b)
    a = b;
}
template <typename T1, typename T2> inline void chmax(T1 &a, T2 b) {
  if (a < b)
    a = b;
}
typedef pair<int, int> P;
const int MOD = 998244353;
const int MAX = 200020;
const double pi = acos(-1);
const double EPS = 1e-12;
const ll INF = 2e18;

long long fac[MAX], finv[MAX], inv[MAX];

// テーブルを作る前処理
void COMinit() {
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < MAX; i++) {
    fac[i] = fac[i - 1] * i % MOD;
    inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
    finv[i] = finv[i - 1] * inv[i] % MOD;
  }
}

// 二項係数計算
long long COM(int n, int k) {
  if (n < k)
    return 0;
  if (n < 0 || k < 0)
    return 0;
  return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
ll add(ll x, ll y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}
ll sub(ll x, ll y) {
  x -= y;
  if (x < 0)
    return x + MOD;
  return x;
}
ll mult(ll x, ll y) { return (x * y) % MOD; }
ll bin_pow(ll x, ll p) {
  if (p == 0)
    return 1;
  if (p & 1)
    return mult(x, bin_pow(x, p - 1));
  return bin_pow(mult(x, x), p / 2);
}

int dp[2020][2020];
int cumR[2020];
int A[2020], B[2020];
int sumR, sumB;
void solve() {
  string S;
  cin >> S;
  int N = S.size();
  COMinit();
  REP(i, N) {
    int num = S[i] - '0';
    A[i] += num;
    B[i] += 2 - num;
    cumR[i + 1] += cumR[i] + A[i];
    sumR += A[i];
    sumB += B[i];
  }
  dp[0][0] = 1;
  REP(i, N) {
    REP(r, N + 1) {
      if (r > 0 && cumR[i + 1] >= r)
        dp[i + 1][r] += dp[i][r - 1];
      int cumB = (i + 1) * 2 - cumR[i + 1];
      if (cumB >= i + 1 - r)
        dp[i + 1][r] += dp[i][r];
      dp[i + 1][r] %= MOD;
      // pe(i+1);pe(r);print(dp[i+1][r]);
    }
  }
  ll ans = 0;

  REP(r, N + 1) {
    ll res = mult(dp[N][r], fac[N]);
    res = mult(res, mult(finv[sumR - r], finv[sumB - (N - r)]));
    ans = add(ans, res);
  }
  print(ans);
}

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  solve();
}