CF1716D 解题报告

更好的体验

CF1716D 解题报告

题目大意:给 n,k,问从 0 开始,第 i 步只能走 (k+i1) 的倍数,问分别走到 x[1,n] 的方案数。

题解

转换题意,有若干个 (k+i) 大小的物品,取 y[k,y) 都要至少选过一次,问拿出总大小为 x[1,n] 的物品的方案数。

现场打的时候完全没想背包,于是寄了。容易发现这是个完全背包,但是前提是一定每个物品至少选一个。于是考虑滚动数组,分层后每次只由当前层和上一层贡献即可。初始状态第 0 层容量为 0 的方案数为 1

考虑证明这个复杂度,容易发现对于每个容积 i ,其能选的物品 t 满足 tk+j=1t(j1)i ,那么 t 的上界是 O(n)。然后对于每个 i[1,n] 求出这个上界,选第 t 个物品时如果超过 i 的上界,那么 i 就不必枚举了(这个是个小的卡常技巧)。复杂度是 O(nn) 未满。

关于就这个玩意为什么我考场上没想出来?我也不知道。

参考代码

#include<bits/stdc++.h>
#define ll long long
#define db double
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define sky fflush(stdout)
#define gc getchar
#define pc putchar
namespace IO{
	template<class T>
	inline void read(T &s){
		s=0;char ch=gc();bool f=0;
		while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
		while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
		if(ch=='.'){
			T p=0.1;ch=gc();
			while('0'<=ch&&ch<='9') {s=s+p*(ch^48);p/=10;ch=gc();}
		}
		s=f?-s:s;
	}
	template<class T,class ...A>
	inline void read(T &s,A &...a){
		read(s);read(a...);
	}
};
using IO::read;
const int N=2e5+3;
const int mods=998244353;
inline int inc(int x,int y){
	return (x+=y)>=mods?x-mods:x;
}
inline int dec(int x,int y){
	return (x-=y)<0?x+mods:x;
}
inline int mul(int x,int y){
	return 1ll*x*y%mods;
}
int n,k;
int len[N];
int f[2][N],g[N];
int main(){
	file(a);
	read(n,k);
	int t=0,sum=0;
	for(int i=1;i<=n;++i){
		while(i>=(t+1)*k+sum+t){
			sum+=t;
			++t;
		}
		len[i]=t;
	}
	int l=0;bool cur=0;
	f[cur^1][0]=1;
	for(int i=1;i<=len[n];++i,cur^=1){
		while(len[l]<i-1) ++l;
		int b=k+i-1;
		memset(f[cur],0,sizeof(f[cur]) );
		for(int j=l;j+b<=n;++j){
			f[cur][j+b]=inc(f[cur][j+b],inc(f[cur][j],f[cur^1][j]) );
			g[j+b]=inc(g[j+b],f[cur][j+b]);
		}
	}
	for(int i=1;i<=n;++i){
		printf("%d ",g[i]);
	}
	return 0;
}
posted @   cbdsopa  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示