数列递推
给定f(0)f(0)f(0),定义fn=∑i=1nf(nmodi)f_n = \sum\limits_{i = 1} ^{n} f_{(n \mod i)}fn=i=1∑nf(nmodi),求f1,f2,f3,…,fn−1,fnf_1, f_2, f_3, \dots, f_{n - 1}, f_{n}f1,f2,f3,…,fn−1,fn。
∑i=1nf(nmodi)∑i=1nf(n−nii)\sum_{i = 1} ^{n} f_{(n \mod i)}\\ \sum_{i = 1} ^{n} f_{(n - \frac{n}{i} i)}\\ i=1∑nf(nmodi)i=1∑nf(n−ini)
显然ni\frac{n}{i}in具有分块性质,当ni\frac{n}{i}in大于n\sqrt nn时,iii只有n\sqrt nn个选择,可以直接枚举,
否则ni<n\frac{n}{i} < \sqrt nin<n时,可以考虑Si,j=fi+fi−j+…S_{i, j} = f_i + f_{i - j} + \dotsSi,j=fi+fi−j+…一个前缀和来转移。
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10, mod = 998244353;int f[N], s[N][310], n;inline int add(int x, int y) {return x + y < mod ? x + y : x + y - mod;
}inline int sub(int x, int y) {return x >= y ? x - y : x - y + mod;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);scanf("%d %d", &n, &f[0]);for (int i = 1; i < 310; i++) {s[0][i] = f[0];}for (int i = 1; i <= n; i++) {for (int l = 1, r, k; l <= i; l = r + 1) {r = i / (i / l), k = i / l;if (k < 310) {int L = i - k * r, R = i - k * l;f[i] = add(f[i], s[R][k]);if (L > k) {f[i] = sub(f[i], s[L - k][k]);}}else {for (int j = l; j <= r; j++) {f[i] = add(f[i], f[i - k * j]);}}}for (int j = 1; j < 310; j++) {if (i >= j) {s[i][j] = add(s[i - j][j], f[i]);}else {s[i][j] = f[i];}}}for (int i = 1; i <= n; i++) {printf("%d%c", f[i], i == n ? '\n' : ' ');}return 0;
}