problem
- 观察发现可以有一个疑似nk的dp,意为第i步能走到j的方案数,\(dp[i][j] = \sum dp[i-1][j] (j==i-(s+k)\dot p)\)
- 这里时间和空间都会爆,但是观察发现k最多是根号n级别的那么复杂度就对了。
- 优化转移,一开始想的是前缀和优化,即第i步走到j的可能性求和,\(sum[i][j] = sum[i][j-(s+k)*2] +dp[i-1][j-(s+k)]\)。
- 但是空间爆掉了。观察发现每一步的i之和前面有关,所以可以滚动优化,这样其实直接就做完了。
- 但是在第三步的位置,可以发现可转移的j等价于 \(j=i(mod (s+k))\)所以就可以通过模数求和来优化转移,这样简洁一些。
void solve() {
int n, k;
cin >> n >> k;
vector<int> dp(n + 1, 0), ans(n + 1, 0);
dp[0] = 1;
for (int mn = 0; mn + k <= n; mn += k++) {
vector<int> sum(k, 0);
for (int i = mn; i <= n; i++) {
int cur = dp[i];
dp[i] = sum[i % k];
sum[i % k] = add(sum[i % k], cur);
ans[i] = add(ans[i], dp[i]);
}
}
for (int i = 1; i <= n ;i++) cout << ans[i] << ' ';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// cin >> t;
// prime();
// for (int i = 1; i <= k; i++) {
// sum[i] = sum[i - 1] + pri[i];
// }
while(t--){
solve();
}
}