洛谷P14118 题解

思维路径

首先我们显然可以暴力模拟m次用餐情况,得到答案,但是这显然会超时。

进而模拟整个过程,可以发现每种食材会在会提升第偶数个人的幸福值。

由此我们可以推出在经过偶数圈用餐后,火锅内的食材会恢复到全 \(0\) 的状态,即产生了循环。

因此我们不需要循环 \(m\) 次来计算,而是只需要循环 \(2n\) 次,找出一次循环后的情形,就可以轻松求解。

实现细节

由于 \(m\) 不一定是 \(2n\) 的整数倍,因此还需要算其剩余部分给人带来的幸福值。

鉴于这一过程是包含在整个循环的过程中的,可以在计算循环节的时候一并记录。

AC 代码

#include<bits/stdc++.h>
using namespace std;
const int N=100009;
int T,n,k,m,a[N];
int ok[N],ans[N*2],cnt[N*2];
//cnt为循环节内的答案,ans为剩余部分的答案

void input(){
	cin>>T;
}

void solve(){
	for(int i=0;i<n;i++){//多测清空!!
		ok[i]=0;
		ans[i]=0;
		cnt[i]=0;
	}
	cin>>n>>k>>m;
	for(int i=0;i<n;i++) cin>>a[i];//这里i从0开始是方便后续取模
	int tms=m/(n*2);//循环节个数
	int rmn=m%(n*2);//剩余部分
	for(int i=0;i<n*2;i++){
		if(ok[a[i%n]]){
			ok[a[i%n]]=0;
			if(i<rmn) ans[i%n]++;
			cnt[i%n]++;
		}
		else{
			ok[a[i%n]]=1;
		}
	}
	for(int i=0;i<n;i++){
		cout<<cnt[i]*tms+ans[i]<<" ";
	}
	cout<<"\n";
}

int main(){
	input();
	while(T--){
		solve();
	}
	return 0;
}
posted @ 2025-10-05 17:56  lemon-cyy  阅读(7)  评论(0)    收藏  举报