题解:P11077 「FSLOI Round I」石子

「FSLOI Round I」石子 题解

题目大意

题目的核心是通过特定规则移动石子,直到一方无法操作而失败。我们需要判断游戏的结果是平局(Draw)、小F获胜(F)还是小L获胜(L)。

题意还是太简单了。

关键规则:

  • 每次操作需选择两堆石子 \(i\)\(j\),满足 \(a_i < x < a_j\)\(x\) 为平均值)。
  • \(j\) 堆移 \(k\) 个石子到 \(i\) 堆。
  • 小F先手,双方都采用最优策略。

解题思路

  1. 平局判断:如果存在某堆石子与平均值的差值不是k的倍数,则无法通过操作使所有石子堆达到平衡状态,游戏会无限进行,结果为Draw

  2. 胜负判断:若所有差值都是 \(k\) 的倍数,则可以计算出总的有效操作次数。每次操作会使总操作次数减 \(1\) ,最后:

    • 若总操作次数为奇数,先手小F获胜。
    • 若总操作次数为偶数,后手小L获胜。

代码实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,k,ave,a[200010];
signed main(){
	cin>>t;
	while(t--){
		int sum=0;
		cin>>n>>k;
		for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i];
		ave=sum/n;
		int flg=0;
		// 检查是否存在无法通过k调整到平均值的石子堆
		for(int i=1;i<=n;i++) if(abs(a[i]-ave)%k!=0) flg=1;
		if(flg){
			cout<<"Draw"<<endl;
			continue;
		}
		// 计算总操作次数
		int num=0;
		for(int i=1;i<=n;i++) num+=abs(a[i]-ave)/k;
		num/=2;  // 每次操作会处理两个堆,所以总操作次数是总和的一半
		// 根据操作次数的奇偶性判断胜负
		cout<<(num%2?"F":"L")<<endl;
	}
	return 0;
}

时间&空间复杂度

  • 时间复杂度:\(O(T×n)\) ,其中T是测试用例数量,n 是每堆石子的数量
  • 空间复杂度:\(O(n)\) ,用于存储石子数量的数组。

AC记录

posted @ 2026-05-24 13:42  Synthx  阅读(2)  评论(0)    收藏  举报