こういうの詰めるの時間かかる。サンプルも弱いので、愚直シミュレーション解も実装して、それとの一致を確かめたりなどした!
問題概要
'1'〜'9' のみからなる文字列 が与えられる。この文字列に対して文字列を返す関数
がある。
は次の操作を実施する。
- 最初、
を空文字列とする
に対して、
の末尾に
を
個付け加える
たとえば、 となる。
与えられた文字列 (サイズ
) に
を繰り返し適用したときに、
が 1 桁の数値を表す文字列になるまでの回数を求めよ。ただし、永遠にそうはならない場合は -1 と出力せよ。
制約
考えたこと
まず、'1' 以外の文字が連続する箇所があると、桁数が減少することはなく、1 桁の数値とはなり得ないことがわかった。
よって、 のように、1 以外の数値が連続しない場合のみ考えればよい。色々実験していくうちに、次のように求めればよいことがわかった。考え方としては、最終的に 1 が何個展開されるのかを求めるという感じだ。
に対して、次を実行する。
文字目以降において、すでに '1' が
個分生えているとする
の表す数値を
としたとき、
を
で置き換える
計算量は となる。
コード
#include <bits/stdc++.h> #include <atcoder/modint> using namespace std; using namespace atcoder; using mint = atcoder::modint998244353; int main() { int N; string S; cin >> N >> S; // '1' 以外が連続していないかをチェック for (int i = 0; i+1 < S.size(); ++i) { if (S[i] != '1' && S[i+1] != '1') { cout << -1 << endl; return 0; } } // 何個分の 1 が生えるかを求める mint res = 0; for (int i = N-1; i >= 1; --i) { res += 1; res *= (S[i]-'0'); } cout << res.val() << endl; }