#include #include #include using namespace std; /** * traP 0->1 講習会問題 * 解法: 0...01...1 のブロックごとに、境界線を動かせる位置を数え上げる */ int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string a; if (!(cin >> a)) return 0; int n = a.length(); long long mod = 998244353; // 1. 変化が起こり得ない両端をカット int first_zero = -1; for (int i = 0; i < n; i++) { if (a[i] == '0') { first_zero = i; break; } } int last_one = -1; for (int i = n - 1; i >= 0; i--) { if (a[i] == '1') { last_one = i; break; } } // 01 の順序が存在しない場合は、初期状態の 1 通りのみ if (first_zero == -1 || last_one == -1 || first_zero > last_one) { cout << 1 << endl; return 0; } long long ans = 1; // first_zero から last_one までの区間をブロック分割 for (int i = first_zero; i <= last_one; ) { if (a[i] == '1') { i++; continue; } // '0' の塊の開始 long long zero_cnt = 0; while (i <= last_one && a[i] == '0') { zero_cnt++; i++; } // その直後の '1' の塊を数える long long one_cnt = 0; while (i <= last_one && a[i] == '1') { one_cnt++; i++; } // もし 0...1 という形が見つかれば、 // そのブロック内での境界の選択肢は (zero_cnt + one_cnt) 通り if (one_cnt > 0) { ans = (ans * (zero_cnt + one_cnt)) % mod; } // one_cnt が 0 の場合は、区間の終端にある 0 の塊なので // 他の 1 とペアになれず、状態数は増えない } cout << ans << endl; return 0; }