题目链接:https://syzoj.com/problem/458
题目大意:有n个数字,其中有k个数字出现了奇数次,求这k个数字,其中内存只给4MB,k<=2
题目思路:由于内存极小,所以很容易想到应该是通过位来得到结果。首先是假如只有一个数字是奇数次,那么很简单直接全异或起来,那些出现偶数次的就全消掉了,剩下来的就是答案。如果有两个的话,就说明我们得到的结果是答案异或的结果,那么就需要得到答案之一才能得到所有答案。答案所具有的特点是,一定存在有一个位是只有奇数个1的,所以我们要是能够得到在该位是1的所有数字的异或结果就能得到这个数字本身(其他都消掉了)。那就开一个32的内存,然后对于每一个x,在他是1的位的位置都异或上x,最后对刚才得到的全异或的结果进行搜索,找到一个为1的位置就把这个位置所对应的异或结果取出来,就是答案之一,与结果再异或就是另一个答案
以下是代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
using namespace std;
const int MAXN = 2e4+5;
const int MAXM = 1e5+5;
int a[32];
int main()
{
int n,k,x,ans;
while(~scanf("%d%d",&n,&k)){
memset(a,0,sizeof(a));
ans=0;
rep(i,1,n){
scanf("%d",&x);
ans^=x;
rep(j,0,31){
int temp=1<<j;
if(temp&x){
a[j]^=x;
}
}
}
if(k==1){
printf("%d\n",ans);
}
else{
int p=0;
rep(j,0,31){
int temp=1<<j;
if(temp&ans){
p=a[j];
break;
}
}
int x=ans^p,y=p;
if(x>y)swap(x,y);
printf("%d %d\n",x,y);
}
}
return 0;
}