#define LOCAL
#define _USE_MATH_DEFINES
#include <array>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>
#include <random>
#include <ctime>

using namespace std;

template <typename A, typename B>
ostream& operator <<(ostream& out, const pair<A, B>& a) {
  out << "(" << a.first << "," << a.second << ")";
  return out;
}
template <typename T, size_t N>
ostream& operator <<(ostream& out, const array<T, N>& a) {
  out << "["; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T>
ostream& operator <<(ostream& out, const vector<T>& a) {
  out << "["; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T, class Cmp>
ostream& operator <<(ostream& out, const set<T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "}";
  return out;
}
template <typename U, typename T, class Cmp>
ostream& operator <<(ostream& out, const map<U, T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}";
  return out;
}
#ifdef LOCAL
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
#else
#define trace(...) 42
#endif
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int, int> ii;
const int INF = 1 << 29;
const int MOD = 998244353;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }

struct fast_ios {
  fast_ios() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
  };
} fast_ios_;

const int N = 3e2 + 10;
int C[N * 2][N * 2];
char s[N];
int dp[N][N][N];
bool visit[N][N][N];
int suf[N][2];
int n;

int solve(int pos, int zero, int one) {
  int& ret = dp[pos][zero][one];
  if (ret >= 0) return ret;
  if (pos == n) return ret = C[zero + one][zero];
  if (suf[pos][0] > zero || suf[pos][1] > one) return ret = 0;
  ret = 0;
  // put 0
  if (zero > 0) {
    ret += solve(s[pos] == '0' ? pos + 1 : pos, zero - 1, one);
    ret %= MOD;
  }
  // put 1
  if (one > 0) {
    ret += solve(s[pos] == '1' ? pos + 1 : pos, zero, one - 1);
    ret %= MOD;
  }
  return ret;
}

struct Node {
  int pos, zero, one;
};

int main() {
  for (int i = 0; i < N * 2; ++i) {
    C[i][0] = C[i][i] = 1;
    for (int j = 1; j < i; ++j) {
      C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
    }
  }
  scanf("%s", s);
  n = strlen(s);
  for (int i = n - 1; i >= 0; --i) {
    suf[i][0] = suf[i + 1][0] + (s[i] == '0');
    suf[i][1] = suf[i + 1][1] + (s[i] == '1');
    // trace(i, suf[i][0], suf[i][1]);
  }
  memset(dp, 255, sizeof(dp));
  queue<Node> Q;
  Q.push({0, 0, 0});
  visit[0][suf[0][0]][suf[0][1]] = true;
  while (!Q.empty()) {
    auto [pos, zero, one] = Q.front();
    Q.pop();
    // int len = one + zero + n - pos;
    // int X = zero + suf[pos][0], Y = one + suf[pos][1];
    int cur = solve(pos, zero + suf[pos][0], one + suf[pos][1]);
    // trace(zero, one, len, pos, X, Y, cur);
    // pick 2
    if (pos + 2 <= n) {
      vector<int> cnt(2);
      cnt[s[pos] - '0']++;
      cnt[s[pos + 1] - '0']++;
      for (int i = 0; i <= 1 && i <= cnt[0]; ++i) {
        int j = 1 - i;
        if (j > cnt[1]) continue;
        int nxt_zero = zero + i, nxt_one = one + j;
        if (!visit[pos + 2][suf[pos + 2][0] + nxt_zero][suf[pos + 2][1] + nxt_one]) {
          Q.push({pos + 2, nxt_zero, nxt_one});
          visit[pos + 2][suf[pos + 2][0] + nxt_zero][suf[pos + 2][1] + nxt_one] = true;
        }
      }
    }
    // pick 1
    if (pos + 1 <= n && one + zero >= 1) {
      for (int u = 0; u <= 1 && u <= zero; ++u) {
        int v = 1 - u;
        if (v > one) continue;
        vector<int> cnt = {u, v};
        cnt[s[pos] - '0']++;
        for (int i = 0; i <= 1 && i <= cnt[0]; ++i) {
          int j = 1 - i;
          if (j > cnt[1]) continue;
          int nxt_zero = zero - u + i, nxt_one = one - v + j;
          if (!visit[pos + 1][suf[pos + 1][0] + nxt_zero][suf[pos + 1][1] + nxt_one]) {
            Q.push({pos + 1, nxt_zero, nxt_one});
            visit[pos + 1][suf[pos + 1][0] + nxt_zero][suf[pos + 1][1] + nxt_one] = true;
          }
        }
      }
    }
    // pick 0
    if (one + zero >= 2) {
      for (int u = 0; u <= 2 && u <= zero; ++u) {
        int v = 2 - u;
        if (v > one) continue;
        vector<int> cnt = {u, v};
        for (int i = 0; i <= 1 && i <= cnt[0]; ++i) {
          int j = 1 - i;
          if (j > cnt[1]) continue;
          int nxt_zero = zero - u + i, nxt_one = one - v + j;
          if (!visit[pos][suf[pos][0] + nxt_zero][suf[pos][1] + nxt_one]) {
            Q.push({pos, nxt_zero, nxt_one});
            visit[pos][suf[pos][0] + nxt_zero][suf[pos][1] + nxt_one] = true;
          }
        }
      }
    }
  }
  int ret = 0;
  for (int X = 0; X <= suf[0][0]; ++X) {
    for (int Y = 0; Y <= suf[0][1]; ++Y) {
      for (int pos = n; pos >= 0; --pos) {
        if (X == 0 && Y == 0 && pos == n) continue;
        if (dp[pos][X][Y] >= 0) {
          // trace(X, Y, pos, dp[pos][X][Y]);
          ret = (ret + dp[pos][X][Y]) % MOD;
          break;
        }
      }
    }
  }
  printf("%d\n", ret);
  return 0;
}


Measured memory_bytes: 129236