F. Make Them Similar
Let’s call two numbers similar if their binary representations contain the same number of digits equal to 1. For example:
2 and 4 are similar (binary representations are 10 and 100);
1337 and 4213 are similar (binary representations are 10100111001 and 1000001110101);
3 and 2 are not similar (binary representations are 11 and 10);
42 and 13 are similar (binary representations are 101010 and 1101).
You are given an array of 𝑛 integers 𝑎1, 𝑎2, …, 𝑎𝑛. You may choose a non-negative integer 𝑥, and then get another array of 𝑛 integers 𝑏1, 𝑏2, …, 𝑏𝑛, where 𝑏𝑖=𝑎𝑖⊕𝑥 (⊕ denotes bitwise XOR).
Is it possible to obtain an array 𝑏 where all numbers are similar to each other?
Input
The first line contains one integer 𝑛 (2≤𝑛≤100).
The second line contains 𝑛 integers 𝑎1, 𝑎2, …, 𝑎𝑛 (0≤𝑎𝑖≤230−1).
Output
If it is impossible to choose 𝑥 so that all elements in the resulting array are similar to each other, print one integer −1.
Otherwise, print any non-negative integer not exceeding 230−1 that can be used as 𝑥 so that all elements in the resulting array are similar.
Examples
input
2
7 2
output
1
input
4
3 17 6 0
output
5
input
3
1 2 3
output
-1
input
3
43 12 12
output
1073709057
题意: 给一个100大小的数组,求一个 x ,有 b i = a i b_i = a_i bi=ai ^ x x x,使得最后 b 数组的每个数二进制 1 的个数相同。
Analyse: 写这个题解,完全是为了记录一下这个技巧。很巧妙。
假设答案是 x, C [ i ] [ 0 ] C[i][0] C[i][0] 表示 a i a_i ai ^ x x x 后低15位 二进制1的个数, C [ i ] [ 1 ] C[i][1] C[i][1] 表示 a i a_i ai ^ x x x 后高15位 二进制1的个数
由题意,有 C [ i ] [ 0 ] + C [ i ] [ 1 ] = = C [ i + 1 ] [ 0 ] + C [ i + 1 ] [ 1 ] , f o r ( i i n r a n g e [ 1 , n − 1 ] ) C[i][0] + C[i][1] == C[i + 1][0] + C[i + 1][1], for(i\ \ in\ \ range[1,n\ -\ 1]) C[i][0]+C[i][1]==C[i+1][0]+C[i+1][1],for(i in range[1,n − 1])
那么变化一下等式,其实就是 C [ i ] [ 0 ] − C [ i + 1 ] [ 0 ] = = C [ i + 1 ] [ 1 ] − C [ i ] [ 1 ] , f o r ( i i n r a n g e [ 1 , n − 1 ] ) C[i][0] - C[i + 1][0] == C[i + 1][1] - C[i][1], for(i\ \ in\ \ range[1,n\ -\ 1]) C[i][0]−C[i+1][0]==C[i+1][1]−C[i][1],for(i in range[1,n − 1])
那么这样子,低15位与高15位就分开了
枚举低15位的数 y,高15位的数 z,分别产生两个数组,即等式两边。若两数组完全相同,那么 a n s = y ∣ ( z < < 15 ) ans = y\ |\ (z << 15) ans=y ∣ (z<<15)
低15位求二进制1的个数 = _ _ b u i l t i n _ p o p c o u n t ( \_\_builtin\_popcount( __builtin_popcount( ( a i (a_i (ai ^ x ) x) x) % \% % ( 1 < < 15 ) ) (1 << 15)) (1<<15))
高15位求二进制1的个数 = _ _ b u i l t i n _ p o p c o u n t ( \_\_builtin\_popcount( __builtin_popcount( ( ( a i > > 15 ) ((a_i >> 15) ((ai>>15) ^ x ) ) x)) x))
其中:int __builtin_popcount(int a)函数 // 返回一个数二进制1的个数
Code:
#include<bits/stdc++.h>
#define debug(x) cerr << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a, b) memset((a),b,sizeof(a))
#define rep(i, a, b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define fi first
#define se second
#define ptch putchar
#define CLR(a) while(!(a).empty()) a.pop()
using namespace std;
#ifndef ONLINE_JUDGE
clock_t prostart = clock();
#endif
int a[110],n,ans = -1;
vector<int> v;
map<vector<int>,int> mp;
void dfs1(int i,int x) {
if(i == 15) {
v.clear();
for(int i = 1;i < n;++ i) {
v.pb(__builtin_popcount((a[i + 1] ^ x) % (1 << 15)) - __builtin_popcount((a[i] ^ x) % (1 << 15)));
}
mp[v] = x;
return ;
}
dfs1(i + 1,x);
dfs1(i + 1,x | (1 << i));
}
void dfs2(int i,int x) {
if(i == 15) {
v.clear();
for(int i = 1;i < n;++ i) {
v.pb(__builtin_popcount(((a[i] >> 15) ^ x)) - __builtin_popcount(((a[i + 1] >> 15) ^ x)));
}
if(mp[v]) ans = mp[v] | (x << 15);
return ;
}
dfs2(i + 1,x);
dfs2(i + 1,x | (1 << i));
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
scanf("%d",&n);
for(int i = 1;i <= n;++ i) scanf("%d",&a[i]);
dfs1(0,0);
dfs2(0,0);
printf("%d\n",ans);
#ifndef ONLINE_JUDGE
cerr << "time: " << 1.0 * (clock() - prostart) / CLOCKS_PER_SEC << " s" << endl;
#endif
return 0;
}