题意
思路
参考了题解做法。
设 \(f_{i, j}\) 表示填入 \(i\) 个数字,和为 \(j\) 的方案数。
每次可以填入 \(0\),或者将整个数列 \(+1\)。
\(g_{i, j}\) 表示填入 \(i\) 个数字,且这 \(i\) 个数字中没有 \(0\),何为 \(j\) 的方案数。
易得 \(g_{i, j} = f_{i, j - i}\),表示在 \(i\) 个数字的和为 \(j - i\) 的情况下给每个数字 \(+1\),这样保证了所有数字均不为 \(0\)。
下面看 \(f\) 的转移。
\(f_{i, j} = \sum\limits_{k = 1} ^ {m} g_{i - k, j}\) 表示填入 \(k\) 个 \(0\)。
\(f_{i, j} = f_{i, j - i}\),表示全体 \(+1\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5010, mod = 998244353;
int f[N][N];
int g[N][N];
int sum[N][N];
int n, m;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= m; i++) f[i][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (j >= i) {
g[i][j] = f[i][j - i];
f[i][j] = f[i][j - i];
}
sum[i][j] = (sum[i - 1][j] + g[i][j]) % mod;
int l = i - m, r = i - 1;
(f[i][j] += (sum[r][j] - sum[max(0, l - 1)][j]) % mod) %= mod;
}
}
for (int i = 1; i <= n; i++) cout << (g[i][n] + mod) % mod << '\n';
return 0;
}
标签:Count,数字,填入,int,sum,ABC221H,Multiset,mod
From: https://www.cnblogs.com/Yuan-Jiawei/p/18422668