[题解]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;  
}  
posted @ 2024-06-23 00:26  WBIKPS  阅读(30)  评论(0)    收藏  举报