DP转移方程
表示用
步走距离
总共有多少走法。
其中, ,即为第
步可以走的最小步数。
迭代一次,
两式相减得到:
复杂度
长度为 ,步数最多不会超过
(可推导)。
合起来时间复杂度为 。
如果直接上二维DP,空间复杂度会很大,考虑转移方程中 只与前面一项有关,可以优化掉一维。优化后空间复杂度为
。
C++代码
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int mod=998244353;
int n,k;
void solve(){
cin>>n>>k;
vector<int> f(n+5); //一维优化空间
vector<int> res(n+5);
f[0]=1; //初始化
int t=(int)sqrt(2*n); //最多走t步
//f(i,j)=f(i-m,j-1)+f(i-m,j)
for(int j=1;j<=t;j++){
//从后往前遍历(要的是j-1)
//f(i,j)=f(i-m,j-1)
for(int i=n;i;i--){
int m=k+j-1;
if(i-m>=0)
f[i]=f[i-m];
else
f[i]=0;
}
f[0]=0;
//从前往后遍历(要的是j)
//f(i,j)+=f(i-m,j)
for(int i=1;i<=n;i++){
int m=k+j-1;
if(i-m>=0)
f[i]=(f[i]+f[i-m])%mod;
}
for(int i=1;i<=n;i++){
res[i]=(res[i]+f[i])%mod; //累加记录结果
}
}
for(int i=1;i<=n;i++){
cout<<res[i]<<" ";
}
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T=1;
while(T--){
solve();
}
return 0;
}