結果
| 問題 | No.3500 01 String |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-04-18 01:30:18 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 1,900 bytes |
| 記録 | |
| コンパイル時間 | 1,100 ms |
| コンパイル使用メモリ | 161,320 KB |
| 実行使用メモリ | 6,400 KB |
| 最終ジャッジ日時 | 2026-04-18 01:30:27 |
| 合計ジャッジ時間 | 2,097 ms |
|
ジャッジサーバーID (参考情報) |
judge3_1 / judge1_1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 WA * 2 |
| other | AC * 3 WA * 17 |
ソースコード
#include <iostream>
#include <string>
#include <vector>
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;
}