题解:P13363 [GCJ 2011 Qualification]
题解:P13363 [GCJ 2011 Qualification]
题目链接
题目翻译
Sean 和 Patrick 兄弟从父母那里得到了一袋糖果。每颗糖果都有一个正整数值,他们想把糖果分成两堆。首先,Sean 将糖果分成两堆,并选择一堆给 Patrick。然后,Patrick 会计算每堆糖果的价值(即堆中所有糖果值的总和)。如果他发现两堆的价值不相等,就会开始哭闹。
Patrick 还很小,不会正确的加法。他只会一种近似的二进制加法:当两个
1100
+ 0101
------
1001
结果得到
5 + 4 = 1
7 + 9 = 14
50 + 10 = 56
Sean 擅长加法,希望在不惹哭弟弟的情况下,尽可能多地拿走糖果的价值。我们需要判断是否可以将糖果分成两堆,使得 Patrick 认为两堆的价值相等。如果可能,求出 Sean 能拿走的堆的最大价值。
输入格式
第一行是测试用例数
输出格式
对于每个测试用例,输出 "Case #x: y",其中
思路
观察题目样例很容易发现,Patrick 的加法实际上是按位异或。因此,我们把问题转化为如何才能使得两堆的异或和相等。设总异或和为
若总异或和为
Code
#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;
}