给出
个整数
,要求选出一个整数
,最小化
,输出这个最小值.
.
这道题直接去构造
,或者以
为依据进行dp是有问题的(掉分的血泪教训,不再展开),而应该直接去贪心求这个最小值.
设最小值的答案是
,对于第
位,如果
个数中第
位为
或
都存在,那么
就一定要加上
,也即
的第
位为
.反之如果
或
有一个不存在,那么这一位取反就可使
第
位为
.
因此我们可以建出Trie树,在树上从高位往低位进行贪心.对于第
位的节点,如果左右儿子都有,这个节点答案就加上
,然后再对子树答案取
即可.时间复杂度就是Trie树的
,但空间多大不是很确定…
总之对于这种可以看出有贪心性质的题,就不要在一棵树上吊死了吧
我 演 我 自 己
#include<bits/stdc++.h>
#define ll long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=100005;
const ll mod=1e9+7;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,a[N],ch[N*21][2],tot;
void ins(int x)
{
int now=0;
for(int i=30; i>=0; i--){
bool t=(1<<i)&x;
if(!ch[now][t]){
ch[now][t]=++tot;
ch[tot][0]=ch[tot][1]=0;
}
now=ch[now][t];
}
}
int dfs(int now,int dep)
{
int k0=ch[now][0],k1=ch[now][1],ret=0;
if(!k0 && !k1) return 0;
if(!k0 && k1) {
int retR=dfs(ch[now][1], dep-1);
return retR;
}
if(k0 && !k1) {
int retL=dfs(ch[now][0], dep-1);
return retL;
}
ret+=(1<<dep)+min(dfs(ch[now][0], dep-1), dfs(ch[now][1], dep-1));
return ret;
}
void solve()
{
n=read();
for(int i=1; i<=n; i++){
a[i]=read();
ins(a[i]);
}
int ans=dfs(0, 30);
printf("%d\n",ans);
}
int main()
{
int T=1;
while(T--) solve();
}