思路
定義 \(dp_i\) 表示前 \(i\) 位所能得到的答案。
那麼,不難得出狀態轉移方程,其中 \(X_{i,j}\) 表示 \(X_{i,j}\) 轉為的數字:
\[
dp_i = \sum_{j = 1}^{i - 1}(dp_j \times X_{j + 1 \sim i}) + X_{1,i}
\]
這樣的時間複雜度為 \(\Theta(n^2)\) 過不了,考慮用字首和最佳化。
\[
\begin{aligned}
dp_i =& \sum_{j = 1}^{i - 1}(dp_j \times X_{j + 1,i}) + X_{1,i}\\
=& \sum_{j = 1}^{i - 1}(dp_j \times (10 \times X_{j + 1,i - 1} + X_{i,i})) + X_{1,i}\\
=& 10 \times dp_{i - 1} + X_{i,i} \times \sum_{j = 1}^{i - 1}(dp_j) + X_{1,i}
\end{aligned}
\]
然後用字首和維護一下 \(\sum_{j = 1}^{i - 1}(dp_j)\) 即可。
時間複雜度 \(\Theta(n)\)。
注意:為了程式碼簡介,我們規定 \(dp_0 = sum_0 = 1\),這樣就可以省去 \(X_{1,i}\)。因為每一次 \(sum_i\) 都會多 \(1\),加起來就正好為 \(X_{1,n}\)。
Code
#include <bits/stdc++.h>
#define int long long
#define re register
using namespace std;
const int N = 2e5 + 10,mod = 998244353;
int n;
int dp[N],sum[N];
string s;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> s;
s = ' ' + s;
dp[1] = s[1] - '0';
sum[1] = dp[1] + 1;
for (re int i = 2;i <= n;i++){
dp[i] = (10 * dp[i - 1] + (s[i] - '0') * sum[i - 1]) % mod;
sum[i] = (sum[i - 1] + dp[i]) % mod;
}
printf("%lld",dp[n]);
return 0;
}