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

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key

typedef long long ll;
typedef pair<ll, ll> ii;
typedef vector<int> vi;
typedef long double ld;
typedef tree<ll, null_type, less<ll>, rb_tree_tag,
             tree_order_statistics_node_update>
    pbds;

vector<int> fact;
vector<int> ifact;
vector<int> inv;
vector<int> pow2;
const int MOD = 998244353;
int add(int a, int b) {
  a += b;
  while (a >= MOD)
    a -= MOD;
  return a;
}
void radd(int &a, int b) { a = add(a, b); }
int mult(int a, int b) { return (a * 1LL * b) % MOD; }
void rmult(int &a, int b) { a = mult(a, b); }
int modpow(int a, int b) {
  int r = 1;
  while (b) {
    if (b & 1)
      r = mult(r, a);
    a = mult(a, a);
    b >>= 1;
  }
  return r;
}
int choose(int a, int b) {
  if (a < b)
    return 0;
  if (b == 0)
    return 1;
  if (a == b)
    return 1;
  return mult(fact[a], mult(ifact[b], ifact[a - b]));
}
int inverse(int a) { return modpow(a, MOD - 2); }
void init(int _n) {
  fact.clear();
  ifact.clear();
  inv.clear();
  pow2.clear();
  fact.resize(_n + 1);
  ifact.resize(_n + 1);
  inv.resize(_n + 1);
  pow2.resize(_n + 1);
  pow2[0] = 1;
  ifact[0] = 1;
  fact[0] = 1;
  for (int i = 1; i <= _n; i++) {
    pow2[i] = add(pow2[i - 1], pow2[i - 1]);
    fact[i] = mult(fact[i - 1], i);
    // ifact[i]=mult(ifact[i-1],inv[i]);
  }
  ifact[_n] = inverse(fact[_n]);
  for (int i = _n - 1; i >= 1; i--) {
    ifact[i] = mult(ifact[i + 1], i + 1);
  }
  for (int i = 1; i <= _n; i++) {
    inv[i] = mult(fact[i - 1], ifact[i]);
  }
}

string s;
int suf[333][333]
       [333]; // # of strings s.t. LCS from back with s goes to that long
// length of T, position at s matched, # of 1s
int f[333][333][333];

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> s;
  int n = s.length();
  /*
  pre[0][0][0][0]=1; //prefix of length 0, 0 1s, 0 0s taken
  for(int i=0;i<n;i++)
  {
          for(int j=0;j<=n;j++)
          {
                  for(int k=0;k<=n;k++)
                  {
                          for(int l=0;l<=n;l++)
                          {
                                  if(!pre[i][j][k][l]) continue;
                                  //11
                                  if(i+2<=n) pre[i+2][j+1][k][l]=1;
                                  //01
                                  if(i+2<=n)
                                  {
                                          if(s[i]=='1') pre[i+2][j][k+1][l]=1;
                                          else pre[i+2][j][k][l+1]=1;
                                  }
                                  //10
                                  if(i+2<=n)
                                  {
                                          if(s[i+1]=='1') pre[i+2][j][k+1][l]=1;
                                          else pre[i+2][j][k][l+1]=1;
                                  }
                                  //0
                                  if(j>0)
                                  {
                                          if(s[i]=='1') pre[i+1][j-1][k+1][l]=1;
                                          else pre[i+1][j-1][k][l+1]=1;
                                  }
                                  //1
                                  pre[i+1][j][k][l]=1;
                          }
                  }
          }
  }
  for(int i=0;i<=n;i++)
  {
          for(int j=0;j<=n;j++)
          {
                  for(int k=0;k<=n;k++)
                  {
                          for(int l=0;l<=n;l++)
                          {
                                  if(pre[i][j][k][l]) g[i][k][l]=1;
                          }
                  }
          }
  }
  */
  f[0][0][0] = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        // assert(f[i][j][k]==g[i][j][k]);
        if (!f[i][j][k])
          continue;
        f[i + 1][j][k] = 1;
        if (i + 3 <= n) {
          if (s[i + 2] == '1')
            f[i + 3][j + 1][k] = 1;
          else
            f[i + 3][j][k + 1] = 1;
        }
        if (i + 2 <= n) {
          if (s[i + 1] == '1')
            f[i + 2][j + 1][k] = 1;
          else
            f[i + 2][j][k + 1] = 1;
          if (s[i] == '1')
            f[i + 2][j + 1][k] = 1;
          else
            f[i + 2][j][k + 1] = 1;
        }
        if (j > 0 && s[i] == '0') {
          f[i + 1][j - 1][k + 1] = 1;
        }
        if (j > 0 && s[i] == '1') {
          f[i + 1][j + 1][k - 1] = 1;
        }
      }
    }
  }
  suf[0][n][0] = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        if (suf[i][j][k] == 0)
          continue;
        int v = suf[i][j][k];
        // choose s[j-1]!
        radd(suf[i + 1][j - 1][k], v);
        // choose opposite of s[j-1] sia
        radd(suf[i + 1][j][k + (s[j - 1] == '0')], v);
      }
    }
  }
  int ans = 1; // match completely
  for (int i = 1; i < n; i++) {
    int preans = ans;
    for (int j = 1; j <= n; j++) {
      for (int k = 0; k < n; k++) {
        int v = suf[i][j][k];
        if (v == 0)
          continue;
        // cerr<<i<<' '<<j<<' '<<k<<' '<<v<<'\\n';
        // s[0..j-1]
        // j=1 special care
        int ones = k;
        int zeroes = i - k - (n - j); // length - number of matches
        // cerr<<ones<<' '<<zeroes<<'\\n';
        if (zeroes < 0)
          continue;
        if (zeroes + ones == 0) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
          continue;
        }
        if (j == 1) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
          continue;
        }
        if (f[j][ones][zeroes]) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
        }
      }
    }
    int newans = ans;
    // cerr<<"LENGTH "<<i<<" = "<<add(newans,MOD-preans)<<'\\n';
  }
  cout << ans << '\\n';
}


Error: -11

Fixed submission:

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key

typedef long long ll;
typedef pair<ll, ll> ii;
typedef vector<int> vi;
typedef long double ld;
typedef tree<ll, null_type, less<ll>, rb_tree_tag,
             tree_order_statistics_node_update>
    pbds;

vector<int> fact;
vector<int> ifact;
vector<int> inv;
vector<int> pow2;
const int MOD = 998244353;
int add(int a, int b) {
  a += b;
  while (a >= MOD)
    a -= MOD;
  return a;
}
void radd(int &a, int b) { a = add(a, b); }
int mult(int a, int b) { return (a * 1LL * b) % MOD; }
void rmult(int &a, int b) { a = mult(a, b); }
int modpow(int a, int b) {
  int r = 1;
  while (b) {
    if (b & 1)
      r = mult(r, a);
    a = mult(a, a);
    b >>= 1;
  }
  return r;
}
int choose(int a, int b) {
  if (a < b)
    return 0;
  if (b == 0)
    return 1;
  if (a == b)
    return 1;
  return mult(fact[a], mult(ifact[b], ifact[a - b]));
}
int inverse(int a) { return modpow(a, MOD - 2); }
void init(int _n) {
  fact.clear();
  ifact.clear();
  inv.clear();
  pow2.clear();
  fact.resize(_n + 1);
  ifact.resize(_n + 1);
  inv.resize(_n + 1);
  pow2.resize(_n + 1);
  pow2[0] = 1;
  ifact[0] = 1;
  fact[0] = 1;
  for (int i = 1; i <= _n; i++) {
    pow2[i] = add(pow2[i - 1], pow2[i - 1]);
    fact[i] = mult(fact[i - 1], i);
    // ifact[i]=mult(ifact[i-1],inv[i]);
  }
  ifact[_n] = inverse(fact[_n]);
  for (int i = _n - 1; i >= 1; i--) {
    ifact[i] = mult(ifact[i + 1], i + 1);
  }
  for (int i = 1; i <= _n; i++) {
    inv[i] = mult(fact[i - 1], ifact[i]);
  }
}

string s;
int pre[78][78][78][78];
int g[78][78][78];
int suf[333][333]
       [333]; // # of strings s.t. LCS from back with s goes to that long
// length of T, position at s matched, # of 1s
int f[333][333][333];

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> s;
  int n = s.length();

  pre[0][0][0][0] = 1; // prefix of length 0, 0 1s, 0 0s taken
  for (int i = 0; i < n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        for (int l = 0; l <= n; l++) {
          if (!pre[i][j][k][l])
            continue;
          // 11
          if (i + 2 <= n)
            pre[i + 2][j + 1][k][l] = 1;
          // 01
          if (i + 2 <= n) {
            if (s[i] == '1')
              pre[i + 2][j][k + 1][l] = 1;
            else
              pre[i + 2][j][k][l + 1] = 1;
          }
          // 10
          if (i + 2 <= n) {
            if (s[i + 1] == '1')
              pre[i + 2][j][k + 1][l] = 1;
            else
              pre[i + 2][j][k][l + 1] = 1;
          }
          // 0
          if (j > 0) {
            if (s[i] == '1')
              pre[i + 1][j - 1][k + 1][l] = 1;
            else
              pre[i + 1][j - 1][k][l + 1] = 1;
          }
          // 1
          pre[i + 1][j][k][l] = 1;
        }
      }
    }
  }
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        for (int l = 0; l <= n; l++) {
          if (pre[i][j][k][l])
            g[i][k][l] = 1;
        }
      }
    }
  }

  f[0][0][0] = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        // assert(f[i][j][k]==g[i][j][k]);
        if (!f[i][j][k])
          continue;
        f[i + 1][j][k] = 1;
        if (i + 3 <= n) {
          if (s[i + 2] == '1')
            f[i + 3][j + 1][k] = 1;
          else
            f[i + 3][j][k + 1] = 1;
        }
        if (i + 2 <= n) {
          if (s[i + 1] == '1')
            f[i + 2][j + 1][k] = 1;
          else
            f[i + 2][j][k + 1] = 1;
          if (s[i] == '1')
            f[i + 2][j + 1][k] = 1;
          else
            f[i + 2][j][k + 1] = 1;
        }
        if (j > 0 && s[i] == '0') {
          f[i + 1][j - 1][k + 1] = 1;
        }
        if (j > 0 && s[i] == '1') {
          f[i + 1][j + 1][k - 1] = 1;
        }
      }
    }
  }
  suf[0][n][0] = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 0; k <= n; k++) {
        if (suf[i][j][k] == 0)
          continue;
        int v = suf[i][j][k];
        // choose s[j-1]!
        radd(suf[i + 1][j - 1][k], v);
        // choose opposite of s[j-1] sia
        radd(suf[i + 1][j][k + (s[j - 1] == '0')], v);
      }
    }
  }
  int ans = 1; // match completely
  for (int i = 1; i < n; i++) {
    int preans = ans;
    for (int j = 1; j <= n; j++) {
      for (int k = 0; k < n; k++) {
        int v = suf[i][j][k];
        if (v == 0)
          continue;
        // cerr<<i<<' '<<j<<' '<<k<<' '<<v<<'\\n';
        // s[0..j-1]
        // j=1 special care
        int ones = k;
        int zeroes = i - k - (n - j); // length - number of matches
        // cerr<<ones<<' '<<zeroes<<'\\n';
        if (zeroes < 0)
          continue;
        if (zeroes + ones == 0) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
          continue;
        }
        if (j == 1) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
          continue;
        }
        if (f[j][ones][zeroes]) {
          radd(ans, v);
          // cerr<<"ADDED\\n";
        }
      }
    }
    int newans = ans;
    // cerr<<"LENGTH "<<i<<" = "<<add(newans,MOD-preans)<<'\\n';
  }
  cout << ans << '\\n';
}