题意
有n个数,要求找到一个数x,使得每个数都与x异或后,所有数的二进制表示中的1的数量一样.
数据范围
n ≤ 100 , 0 ≤ 数 , x < 2 30 n\le 100 ,0 \le 数,x< 2^{30} n≤100,0≤数,x<230
解法
meet in middle
分别搜索x的前15位,用一个结构体存n个数二进制表示下1的个数,然后把搜索的结果存下来,然后搜索后15位,将后15位的结果丢到hash表中.最后枚举前15位的搜索结果,再hash表中查是否有对应的解即可.因为可以任意输出一个解,所以并不复杂.
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
typedef unsigned long long ull;
const ull step=233;
inline int read(){
char c=getchar();int t=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
struct node{
int a[105];
}ch[1<<15],ch2[1<<15];
int n,a[maxn],cnt=-1;
const int sz=2e6;
vector<int> ha[sz];
int cnt2=-1,num1[1<<15],num2[1<<15];
void dfs1(int now,int lim,int alfa){
if(now==lim+1){
cnt++;
for(int i=1;i<=n;i++){
int tmp=a[i]^alfa,tot=0;
for(int i=0;i<=14;i++){
if(tmp&(1<<i))tot++;
}
ch[cnt].a[i]=tot;
}num1[cnt]=alfa;
return ;
}
dfs1(now+1,lim,alfa|(1<<now));
dfs1(now+1,lim,alfa);
}
void dfs2(int now,int lim,int alfa){
if(now==lim+1){
cnt2++;
for(int i=1;i<=n;i++){
int tmp=(a[i]^alfa),tot=0;
for(int i=15;i<=29;i++){
if(tmp&(1<<i))tot++;
}
ch2[cnt2].a[i]=tot;
}num2[cnt2]=alfa;
ull sum=0;
for(int i=1;i<=n;i++){
sum=sum*step+ch2[cnt2].a[i];
}
ha[sum%sz].push_back(cnt2);
return ;
}
dfs2(now+1,lim,alfa|(1<<now));
dfs2(now+1,lim,alfa);
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
dfs1(0,14,0);
dfs2(15,29,0);
for(int i=1;i<=cnt;i++){
node tmp;
int mn=0;
for(int j=1;j<=n;j++){
mn=max(mn,ch[i].a[j]);
}
for(int j=mn;j<=30;j++){
ull sum=0;
for(int k=1;k<=n;k++){
tmp.a[k]=j-ch[i].a[k];
sum=sum*step+tmp.a[k];
}
int pos=sum%sz;
for(int k=0;k<ha[pos].size();k++){
int flag=1;
for(int u=1;u<=n;u++){
if(ch2[ha[pos][k]].a[u]!=tmp.a[u]){flag=0;break;}
}
if(flag){
printf("%d\n",num1[i]+num2[ha[pos][k]]);return 0;
}
}
}
}
puts("-1");
return 0;
}