D()

做法 1

首先第 \(i\) 次至少会加上数字 \(i\),所以前 \(i\) 次跳最少会到 \(\cfrac{i(i+1)}{2}\),所以跳的次数最大是根号级别的。

我们直接枚举操作到第几次,每次计算一个类似前缀和的数组来更新答案,每次都累加答案即可,类似于.复杂度为 \(O(n\sqrt n)\)

前缀和优化DP
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 5, mod = 998244353;
LL f[maxn], sum[maxn], ans[maxn];

int main(){

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int n, k;
    cin >> n >> k;
    f[0] = 1;
    for(int i = 1; ; i++){
        int t = k + i - 1;
        for(int j = 0; j <= n; j++){
            sum[j] = f[j];
            if (j - t >= 0) sum[j] = (sum[j] + sum[j - t]) % mod;
        }
        for(int j = 0; j < t; j++) f[j] = 0;
        for(int j = t; j <= n; j++) f[j] = sum[j - t];
        for(int j = t; j <= n; j++) ans[j] = (ans[j] + f[j]) % mod;
        if (1LL * i * (k + k + i - 1) > n * 2) break;
    }
    for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];

}

做法 2

#include<bits/stdc++.h>
#define h ((m+i)*(i-m+1)/2)
using namespace std;
const int mod=998244353;
int n,m,ans[200005];
int dp[200005] = {1};
int main() {
	cin >> n >> m;
	for(int i=m; h<=n; i++) {
		for(int j=i; j<=n; j++) {
			dp[j]=(dp[j]+dp[j-i])%mod;
		}
		for(int j=h; j<=n; j++) {
			ans[j]=(ans[j]+dp[j-h])%mod;
		}
	}
	for(int i=1; i<=n; i++) {
		cout << ans[i] << " ";
	}
	return 0;
}
————————

做法 1

首先第 \(i\) 次至少会加上数字 \(i\),所以前 \(i\) 次跳最少会到 \(\cfrac{i(i+1)}{2}\),所以跳的次数最大是根号级别的。

我们直接枚举操作到第几次,每次计算一个类似前缀和的数组来更新答案,每次都累加答案即可,类似于.复杂度为 \(O(n\sqrt n)\)

前缀和优化DP
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 5, mod = 998244353;
LL f[maxn], sum[maxn], ans[maxn];

int main(){

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int n, k;
    cin >> n >> k;
    f[0] = 1;
    for(int i = 1; ; i++){
        int t = k + i - 1;
        for(int j = 0; j <= n; j++){
            sum[j] = f[j];
            if (j - t >= 0) sum[j] = (sum[j] + sum[j - t]) % mod;
        }
        for(int j = 0; j < t; j++) f[j] = 0;
        for(int j = t; j <= n; j++) f[j] = sum[j - t];
        for(int j = t; j <= n; j++) ans[j] = (ans[j] + f[j]) % mod;
        if (1LL * i * (k + k + i - 1) > n * 2) break;
    }
    for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];

}

做法 2

#include<bits/stdc++.h>
#define h ((m+i)*(i-m+1)/2)
using namespace std;
const int mod=998244353;
int n,m,ans[200005];
int dp[200005] = {1};
int main() {
	cin >> n >> m;
	for(int i=m; h<=n; i++) {
		for(int j=i; j<=n; j++) {
			dp[j]=(dp[j]+dp[j-i])%mod;
		}
		for(int j=h; j<=n; j++) {
			ans[j]=(ans[j]+dp[j-h])%mod;
		}
	}
	for(int i=1; i<=n; i++) {
		cout << ans[i] << " ";
	}
	return 0;
}