题解 CF 2173 Div2

题解 CF 2173 Div2, 去往 我的网志 阅读体验更佳.

这是我第一次不用翻译直接读英文 statement 的打 cf, 感觉发挥的还不错, 加了二百多分.

problem:CodeForces-2173A 上课睡觉

常言道 "上课睡觉, 下课尿尿, 考试啥也不知道", 其实我们只要在专业课不睡觉就行了, 水课点完名直接睡觉也不会有事的, 期末考试之前两节课跟着教授画一下重点就能通过了.

这个题是说给你弦 \(s\), \(s_{x}==\texttt{1}\) 表示这节课是专业课, \(s_{x}==\texttt{0}\) 表示这节课是水课, 如果第 \(x\) 节课是专业课那么 \([x,x+k]\) 的课上你无法睡觉, 求能睡几节课.

显然, 我们用变量 \(recall\) 记录上次专业课的时间, 如果当前是水课就用上次专业课的时间来判断这节课能否睡觉, 如果当前是专业课就更新 \(recall\).

void	Solve(void){
	ll n,k,fusu=0,recall=~inf;	// 初始化专业课时间为很久很久以前
	std::string s;
	std::cin>>n>>k>>s;
	for(ll x=0;x<n;x++){
		if(s[x]=='0')
			fusu+=recall+k<x;	// 如果本次水课距离上次专业课的距离 >k 则统计
		else	recall=x;		// 更新上次专业课的时间
	}	std::cout<<fusu<<"\n";
}

problem:CodeForces-2173B 尼克的游戏亡卡牌

你有一个变量 \(k\), 初始有 \(k=0\).

\(n\) turns, 第 \(x\) turn 里你会获得 \(a_{x}\)\(b_{x}\), 你可以选择:

  • \(k:=k-a_{x}\).
  • \(k:=b_{x}-k\).

\(n\) turns 完成后, 你的数字最大是多少?

我并不知道我如何想到维护 \(f_{x}\) 为第 \(x\) turn 时的最大值而 \(g_{x}\) 为第 \(x\) turn 时的最小值的, 所以我们直接开始转移.

void	Solve(void){
	ll n;
	std::cin>>n;
	for(ll x=1;x<=n;x++)
		std::cin>>a[x];
	for(ll x=1;x<=n;x++)
		std::cin>>b[x];
	for(ll x=1;x<=n;x++){
		f[x]=f[x-1]-a[x];
		f[x]=std::max(f[x],b[x]-f[x-1]);
		f[x]=std::max(f[x],g[x-1]-a[x]);
		f[x]=std::max(f[x],b[x]-g[x-1]);
		g[x]=f[x-1]-a[x];
		g[x]=std::min(g[x],b[x]-f[x-1]);
		g[x]=std::min(g[x],g[x-1]-a[x]);
		g[x]=std::min(g[x],b[x]-g[x-1]);
	}	std::cout<<f[n]<<"\n";
}

problem:CodeForces-2173C 奏の完美倍数

有数组 \(a_{1..n}\), 你可以构造一个集合 \(b\):

  • \(\forall x\in a\), \(\exist y\in b\) 使得 \(x\bmod y==0\).
  • \(\forall x\in b\), \(\forall y\in\{zx|z\in\N_{+}\&\&zx\le k\}\)\(y\in a\).

求最小的 \(b\).

可以想到从 \(a\) 中每次取出最小的, 如果倍数都在 \(a\) 里就直接放进 \(b\).

void	Solve(void){
	ll n,k;
	std::cin>>n>>k;
	std::set<ll>wblt;	// 用平衡树存储 a 便于找最小
	for(ll x=1,v;x<=n;x++)
		std::cin>>v,
		wblt.insert(v);
	std::set<ll>fusu;
	std::set<ll>recall;
	while(wblt.size()){
		ll v=*wblt.begin();
		wblt.erase(v);
		for(ll x=v<<1;x<=k;x+=v)
			if(wblt.count(x)){
				wblt.erase(x);
				recall.insert(x);
			}else	if(recall.count(x)==0){
				std::cout<<"-1\n";
				return;
			}
		fusu.insert(v);
	}	std::cout<<fusu.size()<<"\n";
	for(ll x:fusu)
		std::cout<<x<<" ";
	std::cout<<"\n";
}
posted @ 2025-12-06 20:23  young_tea  阅读(19)  评论(0)    收藏  举报