http://codeforces.com/problemset/problem/1257/F
题意:
有一个a数组,长度最大100,现在让所有数都异或k,使得得到的数组中,所有数的二进制上的1的个数相同,求这个k。
解析:
考虑异或后的影响,列出对应方程:
我们要求:
,共n-1个方程。一共30位二进制。
考虑折半,枚举前面15位二进制,将对应的式子的答案算出(n-1个答案),哈希这 个答案存到map里面。然后枚举后面15位,算出符合要求时的答案,查看是否存在。
代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ULL unsigned long long
const int maxn=109;
int n;
int a[maxn];
int eqv[maxn][32];
void init(){
rep(i,1,n-1){
int ct=0;
rep(j,0,29){
bool p=0,q=0;
if(a[i]&(1<<j))p=1;
if(a[n]&(1<<j))q=1;
if(p==q)eqv[i][j]=0;
else if(p)eqv[i][j]=-2,ct++;
else eqv[i][j]=2,ct--;
}
eqv[i][30]=-ct;
}
}
unordered_map<ULL,int>Map;
int main(){
scanf("%d",&n);
rep(i,1,n)scanf("%d",a+i);
init();
// 0~14
rep(sta,0,(1<<15)-1){
vector<int>V(n);
rep(i,1,n-1){
int sum=0;
rep(j,0,14){
if(sta&(1<<j))sum+=eqv[i][j];
}
V[i]=sum;
}
ULL H=0;
rep(i,1,n-1){
H=H*23+(ULL)(V[i]);
}
Map[H]=sta;
}
// 15~29
rep(sta,0,(1<<15)-1){
vector<int>V(n);
rep(i,1,n-1){
int sum=0;
rep(j,0,14){
if(sta&(1<<j))sum+=eqv[i][j+15];
}
V[i]=eqv[i][30]-sum;
}
ULL H=0;
rep(i,1,n-1){
H=H*23+(ULL)(V[i]);
}
if(Map.count(H)){
int ans=Map[H];
rep(i,0,14){
if(sta&(1<<i))ans|=(1<<i+15);
}
return 0*printf("%d\n",ans);
}
}
printf("-1\n");
}