#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
const int maxn=1e6+5;
int num[maxn];
int T,n;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int sum=0;
int maxp=0,minp=0;
for(int i=0; i<n; ++i)
{
scanf("%d",&num[i]);
sum^=num[i];
}
int t=1;
while((t&sum)==0)
{
t<<=1;
}
for(int i=0; i<n; ++i)
{
if((num[i]&t)==0)
{
maxp^=num[i];
}
}
minp=sum^maxp;
if(minp>maxp)
printf("%d %d\n",maxp,minp);
else
printf("%d %d\n",minp,maxp);
}
return 0;
}
1.【算法思想】利用最终异或和二进制位从右到做第一个为1的位置:将整个数组所有值分为两类。一类数字在该位置二进制为0,另一类在该位置二进制为1。注意到两个单独出现的数字在这个位置的二进制位一定是不同的。(二进制异或相异为1)所以归为两类之中。两类数字分别异或的结果就是两个数字。
2.注意语法表达的错误(两处):
while((t&sum)==0)
{
t<<=1;
}
【知识点1】==运算符的优先级高于&因此,上面的语句不能写成下面的形式:
while(t&sum==0)
{
t<<=1;
}
【知识点2】t<<=1;是t二进制左移一位的正确表达式。
下面是错误的表达式:
while((t&sum)==0)
{
t<<1;
}
附上一张证明优先级的截图: