#include #include #include #include using namespace std; using ll = long long; #include using namespace atcoder; using mint = modint998244353; int main() { string s; cin >> s; ll n = s.size(); // 各文字列目の時にどの数字を与えるとどのインデックスに移動するか vector q(n + 1, vector(10)); // 正解遷移 for (int i = 0; i < n; i++) q[i][s[i] - '0'] = i + 1; // 不正解の復帰遷移をz-algorithmで調査 auto z = z_algorithm(s); vector revq = { -1,0 }; for (int i = 1; i < n; i++) { ll to = i + z[i]; if (q[to][s[z[i]] - '0'] == 0 && z[i] + 1 < n) { q[to][s[z[i]] - '0'] = z[i] + 1; revq.push_back(z[i] + 1); } } sort(revq.begin(), revq.end()); revq.erase(unique(revq.begin(), revq.end()), revq.end()); unordered_map mrev; for (int i = 0; i < revq.size(); i++) mrev[revq[i]] = i; vector dp(revq.size()); mint r10 = mint(10).inv(); for (int i = n - 1; i >= 0; i--) { vector ndp(dp.size()); ndp[0] = 1; for (int v = 0; v < 10; v++) { if (q[i][v] == i + 1) { for (int di = 0; di < dp.size(); di++) { ndp[di] += dp[di] * r10; } } else { ndp[mrev[q[i][v]]] += r10; } } if (mrev.find(i) != mrev.end() && mrev[i]) { mint div = (-ndp.back() + 1).inv(); for (int i = 0; i < ndp.size() - 1; i++) { ndp[i] *= div; } ndp.pop_back(); } dp = ndp; } dp[0] -= n - 1; cout << dp[0].val(); return 0; }