专栏文章

题解:P13363 [GCJ 2011 Qualification]

P13363题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioszw0y
此快照首次捕获于
2025/12/03 00:39
3 个月前
此快照最后确认于
2025/12/03 00:39
3 个月前
查看原文

题解:P13363 [GCJ 2011 Qualification]

题目翻译

Sean 和 Patrick 兄弟从父母那里得到了一袋糖果。每颗糖果都有一个正整数值,他们想把糖果分成两堆。首先,Sean 将糖果分成两堆,并选择一堆给 Patrick。然后,Patrick 会计算每堆糖果的价值(即堆中所有糖果值的总和)。如果他发现两堆的价值不相等,就会开始哭闹。
Patrick 还很小,不会正确的加法。他只会一种近似的二进制加法:当两个 11 相加时,他会忘记进位。例如,计算 1212,二进制1100110055,二进制 01010101 的和时,他会这样计算:
CPP
  1100
+ 0101
------
  1001
结果得到 99(二进制 10011001),因为他没有正确处理进位。其他例子:
CPP
5 + 4 = 1
7 + 9 = 14
50 + 10 = 56
Sean 擅长加法,希望在不惹哭弟弟的情况下,尽可能多地拿走糖果的价值。我们需要判断是否可以将糖果分成两堆,使得 Patrick 认为两堆的价值相等。如果可能,求出 Sean 能拿走的堆的最大价值。
输入格式
第一行是测试用例数 TT。每个测试用例包含两行:第一行是糖果数 NN,第二行是 NN 个糖果的值 CiC_i
输出格式
对于每个测试用例,输出 "Case #x: y",其中 xx 是测试用例编号。如果无法满足条件,yy 为 "NO";否则,yy 为 Sean 能拿走的堆的最大价值。

思路

观察题目样例很容易发现,Patrick 的加法实际上是按位异或。因此,我们把问题转化为如何才能使得两堆的异或和相等。设总异或和为 sumsum,若 sumsum00,则可以将糖果分成任意两堆,否则无法满足条件。
若总异或和为 00,则 Sean 可以拿走任意一堆,为了保证剩下的子集的异或和与原总异或和均为 00,可以考虑拿走总和最大的子集,其总和为总糖果和减去最小的糖果值。

Code

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,x,s,c[100005];
void solve(int tas)
{
	x=0,s=0;
	memset(c,0,sizeof(c));
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>c[i];
		x^=c[i];
		s+=c[i];
	}
	if(x!=0)
	{
		cout<<"Case #"<<tas<<": NO\n";
		return;
	}
	int mn=1e18;
	for(int i=1;i<=n;i++) mn=min(mn,c[i]);
	cout<<"Case #"<<tas<<": "<<s-mn<<'\n';
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	for(int i=1;i<=t;i++) solve(i);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...