傳送門
題意
n個數,找一個數x使得x與每個數的異或的最大值最小。
思路
首先每個數全寫成二進制的形式,我們可以發現,當第i位上全都相同(同1同0),這一位對最終的max可以沒有貢獻,讓x的這一位與其一樣就抵消了,但是如果2個不一樣,那麼肯定這一位是不能抵消掉的,抵消了這一部分,然後那一部分抵消不了。但是對於這一種情況我們到底怎麼選擇,讓最終的答案最小,得由二進制右邊的那些進行了決定才能對於這2種情況做一個選擇。
所以我們用01字典樹來進行存儲,因爲這一位上如果存在不一樣,肯定是隻有這一位相同的分爲一部分,另一些爲一部分。
code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
typedef long long ll;
const ll mod = 1e9+7;
int tr[30*man][2];
int cnt = 0;
void insert(int x){//字典樹插入
int p = 0;
for(int i = 29;i >= 0;i--){
int tp = x>>i&1;
if(!tr[p][tp])tr[p][tp] = ++cnt;
p = tr[p][tp];
}
}
int dfs(int p,int b){//求答案
if(b<0)return 0;
if(tr[p][0]==0){//全部爲1
return dfs(tr[p][1],b-1);
}else if(tr[p][1]==0){//全部爲0
return dfs(tr[p][0],b-1);
}else{//都有,那麼就分2部分找一個最小值。
return (1<<b) + min(dfs(tr[p][1],b-1),dfs(tr[p][0],b-1));//因爲前面都一樣
//這一位無論怎麼取,都會有一個2^b的貢獻
}
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
cin >>n;
for(int i = 1;i <= n;i++){
int x;
cin >>x;
insert(x);
}
cout << dfs(0,29) << endl;
return 0;
}