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

#ifndef __INTMOD_H__
#define __INTMOD_H__

/* updated: 2019-10-10 */

#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <unordered_map>
#include <vector>

template <uint32_t Mod> class IntMod {
  static_assert(Mod != 0, "Mod must not be 0");
  static_assert(Mod < 0x80000000, "Mod must be less than 0x80000000");

private:
  uint32_t value_m;

public:
  IntMod();
  IntMod(int32_t value);
  IntMod(uint32_t value);
  IntMod(int64_t value);
  IntMod(uint64_t value);

  const IntMod<Mod> &operator+() const;
  IntMod<Mod> operator-() const;
  IntMod<Mod> &operator++();
  IntMod<Mod> &operator--();
  IntMod<Mod> operator++(int dummy);
  IntMod<Mod> operator--(int dummy);
  IntMod<Mod> &operator+=(const IntMod<Mod> &right);
  IntMod<Mod> &operator-=(const IntMod<Mod> &right);
  IntMod<Mod> &operator*=(const IntMod<Mod> &right);
  IntMod<Mod> &operator/=(const IntMod<Mod> &right);
  IntMod<Mod> operator[](uint64_t exp) const;

  static IntMod<Mod> add(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> subtract(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> multiply(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> divide(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static int compare(const IntMod<Mod> &a, const IntMod<Mod> &b);

  IntMod<Mod> inverse() const;
  IntMod<Mod> power(uint64_t exp) const;
  uint32_t get() const;

  static IntMod<Mod> fact(uint32_t num);
  static IntMod<Mod> invFact(uint32_t num);
  static IntMod<Mod> combi(uint32_t n, uint32_t r);
  static IntMod<Mod> homcombi(uint32_t n, uint32_t r);
  static IntMod<Mod> perm(uint32_t n, uint32_t r);
  static std::vector<IntMod<Mod>> calcInverseList(int max);
};

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b);

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object);
template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object);

using MInt = IntMod<1000000007>;
using MF = IntMod<998244353>;

// for unordered_set/map
namespace std {
template <uint32_t Mod> struct hash<IntMod<Mod>> {
  size_t operator()(const IntMod<Mod> &object) const {
    return std::hash<uint32_t>()(object.get());
  }
};
} // namespace std

template <uint32_t Mod>
uint32_t discreteLog(const IntMod<Mod> &a, const IntMod<Mod> &b);

/*------------------------------------*/
/*-------   Implementations   --------*/
/*------------------------------------*/

template <uint32_t Mod> IntMod<Mod>::IntMod() : value_m(0) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int32_t value) {
  int32_t tmp = value % int32_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint32_t value) : value_m(value % Mod) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int64_t value) {
  int32_t tmp = value % int64_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint64_t value) : value_m(value % Mod) {}

template <uint32_t Mod> const IntMod<Mod> &IntMod<Mod>::operator+() const {
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator-() const {
  IntMod<Mod> ret;
  if (value_m == 0) {
    ret.value_m = 0;
  } else {
    ret.value_m = Mod - value_m;
  }
  return ret;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator++() {
  ++value_m;
  if (value_m == Mod) {
    value_m = 0;
  }
  return *this;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator--() {
  if (value_m == 0) {
    value_m = Mod;
  }
  --value_m;
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator++(int dummy) {
  IntMod ret(*this);
  ++*this;
  return ret;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator--(int dummy) {
  IntMod ret(*this);
  --*this;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator+=(const IntMod<Mod> &right) {
  value_m += right.value_m; // note: value_m < 0x80000000
  if (value_m >= Mod) {
    value_m -= Mod;
  }
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator-=(const IntMod<Mod> &right) {
  if (value_m < right.value_m) {
    value_m += Mod; // note: value_m < 0x80000000
  }
  value_m -= right.value_m;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator*=(const IntMod<Mod> &right) {
  value_m = (uint64_t(value_m) * right.value_m) % Mod;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator/=(const IntMod<Mod> &right) {
  *this *= right.inverse();
  return *this;
}

// for power
template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::operator[](uint64_t exp) const {
  return power(exp);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::add(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret += b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::subtract(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret -= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::multiply(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret *= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::divide(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret /= b;
  return ret;
}

template <uint32_t Mod>
int IntMod<Mod>::compare(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  if (a.value_m < b.value_m)
    return -1;
  if (a.value_m > b.value_m)
    return 1;
  return 0;
}

/* Mod must be a prime. */
template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::inverse() const {
  assert(value_m != 0);
  return power(Mod - 2);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::power(uint64_t exp) const {
  IntMod<Mod> product(1);
  IntMod<Mod> factor(*this);
  while (exp > 0) {
    if (exp & 1) {
      product *= factor;
    }
    factor *= factor;
    exp >>= 1;
  }
  return product;
}

template <uint32_t Mod> uint32_t IntMod<Mod>::get() const { return value_m; }

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::fact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  for (uint32_t i = old_size; i <= num; ++i) {
    table[i] = table[i - 1] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::invFact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  table[num] = fact(num).inverse();
  for (uint32_t i = num; i >= old_size; --i) {
    table[i - 1] = table[i] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::combi(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r) * invFact(r);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::homcombi(uint32_t n, uint32_t r) {
  assert(n != 0 || r == 0);

  if (n == 0 && r == 0)
    return IntMod<Mod>(1);
  return combi(n + r - 1, r);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::perm(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) / fact(n - r);
}

template <uint32_t Mod>
std::vector<IntMod<Mod>> IntMod<Mod>::calcInverseList(int max) {
  assert(max < Mod);

  std::vector<IntMod<Mod>> table(max + 1);
  table[1] = 1;
  for (int i = 2; i <= max; ++i) {
    table[i] = (uint64_t(Mod - Mod / i) * table[Mod % i].get()) % Mod;
  }
  return table;
}

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::add(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::subtract(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::multiply(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::divide(a, b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b) {
  return a + IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b) {
  return a - IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b) {
  return a * IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b) {
  return a / IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) + b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) - b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) * b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) / b;
}

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) == 0;
}

template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) != 0;
}

template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) < 0;
}

template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) <= 0;
}

template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) > 0;
}

template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) >= 0;
}

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b) {
  return a == IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b) {
  return a != IntMod<Mod>(b);
}

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object) {
  uint64_t value;
  ist >> value;
  object = IntMod<Mod>(value);
  return ist;
}

template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object) {
  ost << object.get();
  return ost;
}

#endif

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DynamicMod.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Range.h"
#include "Rational.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

using M9 = IntMod<998244353>;

// T = reverse(S) とする
// 以下、「T 内の文字」と言った場合、先頭から貪欲に T
// に含まれる文字を確定していくことを示す T = "100101" に対して 0 を3つ挿入し、
// "100010010" を得たなら、 [1][0][0] 0 [1][0] 0 [1] となる ([ ] のついた部分が
// T 内の文字)

string S;
bool DP[302][302][302]; // DP[i][j][k] = Sの先頭 i 文字を使って手持ちを「0 が j
                        // 個, 1 が k 個」にできるか
M9 EP[302][302]; // EP[i][j] = Tの先頭 i 文字に 0 を j
                 // 個挿入してできる文字列で、末尾が T 内の文字であるものの数
M9 FP[302][302]; // FP[i][k] = Tの先頭 i 文字に 1 を k
                 // 個挿入してできる文字列で、末尾が T 内の文字であるものの数
M9 GP[302][302][302]; // GP[i][j][k] = Tの先頭 i 文字に 0 を j 個, 1 を k
                      // 個挿入してできる文字列の数
M9 EQ[302][303]; // 累積和用
M9 FQ[302][303];
void pre() {
  string T = S;
  reverse(T.begin(), T.end());
  int N = T.size();

  // EP の計算: 先頭から T を見ていき 0 を挿入する ([1] の前のみに挿入できる)
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      if (i == 0) {
        EP[i][0] = 1;
      } else if (T[i - 1] == '0') {
        EP[i][j] = EP[i - 1][j];
      } else {
        EP[i][j] = EQ[i - 1][j + 1];
      }
    }

    REP(j, 0, N + 1) { EQ[i][j + 1] = EQ[i][j] + EP[i][j]; }
  }

  // FP の計算: 先頭から T を見ていき 1 を挿入する ([0] の前のみに挿入できる)
  REP(i, 0, N + 1) {
    REP(k, 0, N + 1) {
      if (i == 0) {
        FP[i][0] = 1;
      } else if (T[i - 1] == '0') {
        FP[i][k] = FQ[i - 1][k + 1];
      } else {
        FP[i][k] = FP[i - 1][k];
      }
    }

    REP(k, 0, N + 1) { FQ[i][k + 1] = FQ[i][k] + FP[i][k]; }
  }

  // GP の計算:
  // GP[i][j][k] = sum [p = 0 to j, q = 0 to k] { EP[i][j - p] * FP[i][k - q] *
  // C(p + q, p) } である (T 内の文字がどこに現れるかで場合分けするとわかる)
  // ここから GP[i][j][k] = GP[i][j - 1][k] + GP[i][j][k - 1] + EP[i][j] *
  // FP[i][k] が得られる
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        GP[i][j][k] += EP[i][j] * FP[i][k];
        if (j > 0)
          GP[i][j][k] += GP[i][j - 1][k];
        if (k > 0)
          GP[i][j][k] += GP[i][j][k - 1];
      }
    }
  }
}

int main() {
  cin >> S;
  pre();

  int N = S.size();

  // DP の計算 (これは素直だと思います)
  DP[0][0][0] = true;
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        if (i + 1 < N) {
          if (S[i] == '0' || S[i + 1] == '0')
            DP[i + 2][j + 1][k] |= DP[i][j][k];
          if (S[i] == '1' || S[i + 1] == '1')
            DP[i + 2][j][k + 1] |= DP[i][j][k];
        }
        if (j > 0 && S[i] == '1')
          DP[i + 1][j - 1][k + 1] |= DP[i][j][k];
        if (k > 0 && S[i] == '0')
          DP[i + 1][j + 1][k - 1] |= DP[i][j][k];
        if (j + k > 0)
          DP[i + 1][j][k] |= DP[i][j][k];
      }
    }
  }

  M9 sum = 0;
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        if (!DP[i][j][k])
          continue;
        // 今見ている取り除き方 (i, j, k)
        // を包含するようなうまい取り除き方があれば skip
        if (S[i] == '0' && DP[i + 1][j + 1][k])
          continue;
        if (S[i] == '1' && DP[i + 1][j][k + 1])
          continue;
        sum += GP[N - i][j][k];
      }
    }
  }
  cout << sum << endl;
  return 0;
}

Error: -11

Fixed submission:

#ifndef __INTMOD_H__
#define __INTMOD_H__

/* updated: 2019-10-10 */

#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <unordered_map>
#include <vector>

template <uint32_t Mod> class IntMod {
  static_assert(Mod != 0, "Mod must not be 0");
  static_assert(Mod < 0x80000000, "Mod must be less than 0x80000000");

private:
  uint32_t value_m;

public:
  IntMod();
  IntMod(int32_t value);
  IntMod(uint32_t value);
  IntMod(int64_t value);
  IntMod(uint64_t value);

  const IntMod<Mod> &operator+() const;
  IntMod<Mod> operator-() const;
  IntMod<Mod> &operator++();
  IntMod<Mod> &operator--();
  IntMod<Mod> operator++(int dummy);
  IntMod<Mod> operator--(int dummy);
  IntMod<Mod> &operator+=(const IntMod<Mod> &right);
  IntMod<Mod> &operator-=(const IntMod<Mod> &right);
  IntMod<Mod> &operator*=(const IntMod<Mod> &right);
  IntMod<Mod> &operator/=(const IntMod<Mod> &right);
  IntMod<Mod> operator[](uint64_t exp) const;

  static IntMod<Mod> add(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> subtract(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> multiply(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static IntMod<Mod> divide(const IntMod<Mod> &a, const IntMod<Mod> &b);
  static int compare(const IntMod<Mod> &a, const IntMod<Mod> &b);

  IntMod<Mod> inverse() const;
  IntMod<Mod> power(uint64_t exp) const;
  uint32_t get() const;

  static IntMod<Mod> fact(uint32_t num);
  static IntMod<Mod> invFact(uint32_t num);
  static IntMod<Mod> combi(uint32_t n, uint32_t r);
  static IntMod<Mod> homcombi(uint32_t n, uint32_t r);
  static IntMod<Mod> perm(uint32_t n, uint32_t r);
  static std::vector<IntMod<Mod>> calcInverseList(int max);
};

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b);
template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b);

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b);
template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b);

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b);
template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b);

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object);
template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object);

using MInt = IntMod<1000000007>;
using MF = IntMod<998244353>;

// for unordered_set/map
namespace std {
template <uint32_t Mod> struct hash<IntMod<Mod>> {
  size_t operator()(const IntMod<Mod> &object) const {
    return std::hash<uint32_t>()(object.get());
  }
};
} // namespace std

template <uint32_t Mod>
uint32_t discreteLog(const IntMod<Mod> &a, const IntMod<Mod> &b);

/*------------------------------------*/
/*-------   Implementations   --------*/
/*------------------------------------*/

template <uint32_t Mod> IntMod<Mod>::IntMod() : value_m(0) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int32_t value) {
  int32_t tmp = value % int32_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint32_t value) : value_m(value % Mod) {}

template <uint32_t Mod> IntMod<Mod>::IntMod(int64_t value) {
  int32_t tmp = value % int64_t(Mod);
  value_m = tmp >= 0 ? tmp : Mod - uint32_t(-tmp);
}

template <uint32_t Mod>
IntMod<Mod>::IntMod(uint64_t value) : value_m(value % Mod) {}

template <uint32_t Mod> const IntMod<Mod> &IntMod<Mod>::operator+() const {
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator-() const {
  IntMod<Mod> ret;
  if (value_m == 0) {
    ret.value_m = 0;
  } else {
    ret.value_m = Mod - value_m;
  }
  return ret;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator++() {
  ++value_m;
  if (value_m == Mod) {
    value_m = 0;
  }
  return *this;
}

template <uint32_t Mod> IntMod<Mod> &IntMod<Mod>::operator--() {
  if (value_m == 0) {
    value_m = Mod;
  }
  --value_m;
  return *this;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator++(int dummy) {
  IntMod ret(*this);
  ++*this;
  return ret;
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::operator--(int dummy) {
  IntMod ret(*this);
  --*this;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator+=(const IntMod<Mod> &right) {
  value_m += right.value_m; // note: value_m < 0x80000000
  if (value_m >= Mod) {
    value_m -= Mod;
  }
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator-=(const IntMod<Mod> &right) {
  if (value_m < right.value_m) {
    value_m += Mod; // note: value_m < 0x80000000
  }
  value_m -= right.value_m;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator*=(const IntMod<Mod> &right) {
  value_m = (uint64_t(value_m) * right.value_m) % Mod;
  return *this;
}

template <uint32_t Mod>
IntMod<Mod> &IntMod<Mod>::operator/=(const IntMod<Mod> &right) {
  *this *= right.inverse();
  return *this;
}

// for power
template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::operator[](uint64_t exp) const {
  return power(exp);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::add(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret += b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::subtract(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret -= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::multiply(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret *= b;
  return ret;
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::divide(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  IntMod<Mod> ret(a);
  ret /= b;
  return ret;
}

template <uint32_t Mod>
int IntMod<Mod>::compare(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  if (a.value_m < b.value_m)
    return -1;
  if (a.value_m > b.value_m)
    return 1;
  return 0;
}

/* Mod must be a prime. */
template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::inverse() const {
  assert(value_m != 0);
  return power(Mod - 2);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::power(uint64_t exp) const {
  IntMod<Mod> product(1);
  IntMod<Mod> factor(*this);
  while (exp > 0) {
    if (exp & 1) {
      product *= factor;
    }
    factor *= factor;
    exp >>= 1;
  }
  return product;
}

template <uint32_t Mod> uint32_t IntMod<Mod>::get() const { return value_m; }

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::fact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  for (uint32_t i = old_size; i <= num; ++i) {
    table[i] = table[i - 1] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::invFact(uint32_t num) {
  assert(num <= 0x80000000);

  static std::vector<IntMod<Mod>> table(1, 1);
  if (table.size() > num)
    return table[num];

  uint32_t old_size = table.size();
  table.resize(num + 1);
  table[num] = fact(num).inverse();
  for (uint32_t i = num; i >= old_size; --i) {
    table[i - 1] = table[i] * i;
  }
  return table[num];
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::combi(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) * invFact(n - r) * invFact(r);
}

template <uint32_t Mod>
IntMod<Mod> IntMod<Mod>::homcombi(uint32_t n, uint32_t r) {
  assert(n != 0 || r == 0);

  if (n == 0 && r == 0)
    return IntMod<Mod>(1);
  return combi(n + r - 1, r);
}

template <uint32_t Mod> IntMod<Mod> IntMod<Mod>::perm(uint32_t n, uint32_t r) {
  assert(n >= r);
  return fact(n) / fact(n - r);
}

template <uint32_t Mod>
std::vector<IntMod<Mod>> IntMod<Mod>::calcInverseList(int max) {
  assert(max < Mod);

  std::vector<IntMod<Mod>> table(max + 1);
  table[1] = 1;
  for (int i = 2; i <= max; ++i) {
    table[i] = (uint64_t(Mod - Mod / i) * table[Mod % i].get()) % Mod;
  }
  return table;
}

template <uint32_t Mod>
IntMod<Mod> operator+(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::add(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator-(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::subtract(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator*(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::multiply(a, b);
}

template <uint32_t Mod>
IntMod<Mod> operator/(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::divide(a, b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const IntMod<Mod> &a, const Int &b) {
  return a + IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const IntMod<Mod> &a, const Int &b) {
  return a - IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const IntMod<Mod> &a, const Int &b) {
  return a * IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const IntMod<Mod> &a, const Int &b) {
  return a / IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator+(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) + b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator-(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) - b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator*(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) * b;
}

template <uint32_t Mod, class Int>
IntMod<Mod> operator/(const Int &a, const IntMod<Mod> &b) {
  return IntMod<Mod>(a) / b;
}

template <uint32_t Mod>
bool operator==(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) == 0;
}

template <uint32_t Mod>
bool operator!=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) != 0;
}

template <uint32_t Mod>
bool operator<(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) < 0;
}

template <uint32_t Mod>
bool operator<=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) <= 0;
}

template <uint32_t Mod>
bool operator>(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) > 0;
}

template <uint32_t Mod>
bool operator>=(const IntMod<Mod> &a, const IntMod<Mod> &b) {
  return IntMod<Mod>::compare(a, b) >= 0;
}

template <uint32_t Mod, class Int>
bool operator==(const IntMod<Mod> &a, const Int &b) {
  return a == IntMod<Mod>(b);
}

template <uint32_t Mod, class Int>
bool operator!=(const IntMod<Mod> &a, const Int &b) {
  return a != IntMod<Mod>(b);
}

template <uint32_t Mod>
std::istream &operator>>(std::istream &ist, IntMod<Mod> &object) {
  uint64_t value;
  ist >> value;
  object = IntMod<Mod>(value);
  return ist;
}

template <uint32_t Mod>
std::ostream &operator<<(std::ostream &ost, const IntMod<Mod> &object) {
  ost << object.get();
  return ost;
}

#endif

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <vector>

using namespace std;
using uint = uint32_t;
using LL = int64_t;
using ULL = uint64_t;
using PP = pair<LL, LL>;
template <typename T>
using PriorityQ = priority_queue<T, vector<T>, greater<T>>;
#define REP(i, a, n) for (LL i = (a), i##_max_ = (n); i < i##_max_; ++i)
#define REM(i, a, n) for (LL i = (LL)(n)-1, i##_min_ = (a); i >= i##_min_; --i)
#define FLOAT fixed << setprecision(16)
#define SPEEDUP                                                                \\
  {                                                                            \\
    cin.tie(NULL);                                                             \\
    ios::sync_with_stdio(false);                                               \\
  }
const int INF = 0x3FFFFFFF;
const LL INFLL = 0x3FFFFFFF3FFFFFFF;
const double INFD = 1.0e+308;
const double EPS = 1.0e-9;

void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
template <class T, class U>
istream &operator>>(istream &ist, pair<T, U> &right) {
  return ist >> right.first >> right.second;
}
template <class T, class U>
ostream &operator<<(ostream &ost, const pair<T, U> &right) {
  return ost << right.first << ' ' << right.second;
}
template <class T, class TCompatible, size_t N>
void Fill(T (&dest)[N], const TCompatible &val) {
  fill(dest, dest + N, val);
}
template <class T, class TCompatible, size_t M, size_t N>
void Fill(T (&dest)[M][N], const TCompatible &val) {
  for (int i = 0; i < M; ++i)
    Fill(dest[i], val);
}
template <class T> T Next() {
  T buf;
  cin >> buf;
  return buf;
}
istream &Ignore(istream &ist) {
  string s;
  ist >> s;
  return ist;
}
bool Inside(int i, int j, int h, int w) {
  return i >= 0 && i < h && j >= 0 && j < w;
}

#ifdef ONLY_MY_ENVIR
#include "Accumulator.h"
#include "Algebraic.h"
#include "BIT.h"
#include "BinaryMatrix.h"
#include "BinaryTree.h"
#include "Bipartite.h"
#include "Compressor.h"
#include "Decompositions.h"
#include "DynamicMod.h"
#include "FFT.h"
#include "Factorization.h"
#include "FlowSolver.h"
#include "Graph.h"
#include "GraphUtil.h"
#include "IntMod.h"
#include "LIS.h"
#include "LazySegmentTree.h"
#include "Math.h"
#include "MathUtil.h"
#include "Matrix.h"
#include "MinCostFlowSolver.h"
#include "MinMax.h"
#include "Numbers.h"
#include "Optimize.h"
#include "Permutation.h"
#include "Polynomial.h"
#include "Position.h"
#include "Range.h"
#include "Rational.h"
#include "SegmentTree.h"
#include "SegmentTree2D.h"
#include "Sets.h"
#include "Shortest.h"
#include "SlidingWindow.h"
#include "SpanningTree.h"
#include "StringSearching.h"
#include "SuffixArray.h"
#include "SwitchList.h"
#include "Tree.h"
#include "TreeUtil.h"
#include "UnionFind.h"
#include "Util.h"
#include "VectorUtil.h"
#endif

#ifdef __GNUC__
typedef __int128 LLL;
istream &operator>>(istream &ist, __int128 &val) {
  LL tmp;
  ist >> tmp;
  val = tmp;
  return ist;
}
ostream &operator<<(ostream &ost, __int128 val) {
  LL tmp = val;
  ost << tmp;
  return ost;
}
#endif

using M9 = IntMod<998244353>;

// T = reverse(S) とする
// 以下、「T 内の文字」と言った場合、先頭から貪欲に T
// に含まれる文字を確定していくことを示す T = "100101" に対して 0 を3つ挿入し、
// "100010010" を得たなら、 [1][0][0] 0 [1][0] 0 [1] となる ([ ] のついた部分が
// T 内の文字)

string S;
bool DP[301][301][301]; // DP[i][j][k] = Sの先頭 i 文字を使って手持ちを「0 が j
                        // 個, 1 が k 個」にできるか
M9 EP[301][301]; // EP[i][j] = Tの先頭 i 文字に 0 を j
                 // 個挿入してできる文字列で、末尾が T 内の文字であるものの数
M9 FP[301][301]; // FP[i][k] = Tの先頭 i 文字に 1 を k
                 // 個挿入してできる文字列で、末尾が T 内の文字であるものの数
M9 GP[301][301][301]; // GP[i][j][k] = Tの先頭 i 文字に 0 を j 個, 1 を k
                      // 個挿入してできる文字列の数
M9 EQ[301][302]; // 累積和用
M9 FQ[301][302];
void pre() {
  string T = S;
  reverse(T.begin(), T.end());
  int N = T.size();

  // EP の計算: 先頭から T を見ていき 0 を挿入する ([1] の前のみに挿入できる)
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      if (i == 0) {
        EP[i][0] = 1;
      } else if (T[i - 1] == '0') {
        EP[i][j] = EP[i - 1][j];
      } else {
        EP[i][j] = EQ[i - 1][j + 1];
      }
    }

    REP(j, 0, N + 1) { EQ[i][j + 1] = EQ[i][j] + EP[i][j]; }
  }

  // FP の計算: 先頭から T を見ていき 1 を挿入する ([0] の前のみに挿入できる)
  REP(i, 0, N + 1) {
    REP(k, 0, N + 1) {
      if (i == 0) {
        FP[i][0] = 1;
      } else if (T[i - 1] == '0') {
        FP[i][k] = FQ[i - 1][k + 1];
      } else {
        FP[i][k] = FP[i - 1][k];
      }
    }

    REP(k, 0, N + 1) { FQ[i][k + 1] = FQ[i][k] + FP[i][k]; }
  }

  // GP の計算:
  // GP[i][j][k] = sum [p = 0 to j, q = 0 to k] { EP[i][j - p] * FP[i][k - q] *
  // C(p + q, p) } である (T 内の文字がどこに現れるかで場合分けするとわかる)
  // ここから GP[i][j][k] = GP[i][j - 1][k] + GP[i][j][k - 1] + EP[i][j] *
  // FP[i][k] が得られる
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        GP[i][j][k] += EP[i][j] * FP[i][k];
        if (j > 0)
          GP[i][j][k] += GP[i][j - 1][k];
        if (k > 0)
          GP[i][j][k] += GP[i][j][k - 1];
      }
    }
  }
}

int main() {
  cin >> S;
  pre();

  int N = S.size();

  // DP の計算 (これは素直だと思います)
  DP[0][0][0] = true;
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        if (i + 1 < N) {
          if (S[i] == '0' || S[i + 1] == '0')
            DP[i + 2][j + 1][k] |= DP[i][j][k];
          if (S[i] == '1' || S[i + 1] == '1')
            DP[i + 2][j][k + 1] |= DP[i][j][k];
        }
        if (j > 0 && S[i] == '1')
          DP[i + 1][j - 1][k + 1] |= DP[i][j][k];
        if (k > 0 && S[i] == '0')
          DP[i + 1][j + 1][k - 1] |= DP[i][j][k];
        if (j + k > 0)
          DP[i + 1][j][k] |= DP[i][j][k];
      }
    }
  }

  M9 sum = 0;
  REP(i, 0, N + 1) {
    REP(j, 0, N + 1) {
      REP(k, 0, N + 1) {
        if (!DP[i][j][k])
          continue;
        // 今見ている取り除き方 (i, j, k)
        // を包含するようなうまい取り除き方があれば skip
        if (S[i] == '0' && DP[i + 1][j + 1][k])
          continue;
        if (S[i] == '1' && DP[i + 1][j][k + 1])
          continue;
        sum += GP[N - i][j][k];
      }
    }
  }
  cout << sum << endl;
  return 0;
}