Educational Codeforces Round 133 (Rated for Div. 2) Problem D Chip Move

D. Chip Move

DP转移方程

f(i,j) 表示用 j 步走距离 i 总共有多少走法。

f(i,j) = f(i-m,j-1) + f(i-2m,j-1) + f(i-3m,j-1) + ...

其中, m = k+j-1 ,即为第 j 步可以走的最小步数。

迭代一次,

f(i,j) = f(i-m,j-1) + f(i-2m,j-1) + f(i-3m,j-1) + ...

f(i-m,j) = \qquad \qquad \quad \ \ f(i-2m,j-1) + f(i-3m,j-1) + ...

两式相减得到:

\boldsymbol{f(i,j) = f(i-m,j-1) + f(i-m,j)}

复杂度

长度为 n ,步数最多不会超过 \sqrt{2n} (可推导)。

合起来时间复杂度为 \boldsymbol{O(n^{\frac32})} 。

如果直接上二维DP,空间复杂度会很大,考虑转移方程中 j 只与前面一项有关,可以优化掉一维。优化后空间复杂度为 \boldsymbol{O(n)} 。

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值