Description
题目的大致意思是场上有许多血量不同的小魔像,当存在两只小魔像血量相同时,两者之间会产生连线从而降低伤害输出的比例。玩家的任务便是使尽可能多的小魔像配对,两只小魔像的血量相同就算配对成功。
Input
第一行一个整数T,代表数据的组数(1<=T<=10),接下来T组数据,每组数据的第一行是一个整数n(2<=n<=1000000,保证n是偶数),第二行是n个整数ai(0 <= ai <= 1000000000)代表血量,每两个整数之间有一个空格,(输入保证有且只有两个小魔像无法连线)
Output
对于每组数据,输出两个整数,分别代表两个小魔像的血量,中间有一个空格,并且血量较大的先输出。
Sample Input
2
6
2 2 1 1 3 4
4
4 1 1 3 4
Sample Output
4 3
4 3
Analysis
结合题目的输入输出可知,我们需要在给出的数据中找出两只无法配对的小魔像。这里采用异或的方式求解。
因为一个数与同一个数进行两次异或运算值不变,比如3^5^5=3
0 | 1 | 1 | |
---|---|---|---|
^ | 1 | 0 | 1 |
1 | 1 | 0 | |
^ | 1 | 0 | 1 |
0 | 1 | 1 |
将一组数据与0进行异或运算,最后得到的sum就是其中唯一两个不配对的数据的异或结果。while(((sum>>f)&1)==0) f++;
通过将结果不断右移并与1相与,就可以得到这两个数字的最低不同数位,即第f位(f从0开始计数)。比如第一个组数据得到的sum=3^4=111(2)
1 | 1 | 1 | |
---|---|---|---|
& | 0 | 0 | 1 |
0 | 0 | 1 |
条件(sum>>0)&1
为假,得到第0位为最低位。然后以第f位(f=0)是否位0做条件将数据分为两组分别进行异或运算,使得两个不同的数分开,最后将结果排序输出。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
long long a[maxn];
int main(){
int t,n;
cin>>t;
while(t--){
cin>>n;
int sum=0;
for(int i=0;i<n;i++){
cin>>a[i];
sum^=a[i];
}
int f=0;
while(((sum>>f)&1)==0) //注意优先级
f++;
int x=0,y=0;
for(int i=0;i<n;i++){
if((a[i]>>f)&1) x^=a[i];
else y^=a[i];
}
if(x<y) swap(x,y);
cout<<x<<" "<<y<<endl;
}
return 0;
}