[题解]AT_abc288_f [ABC288F] Integer Division
思路
定义 \(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;
}

浙公网安备 33010602011771号