思路 字典树
显然不能枚举所有的点求两两见的异或值, 我们知道表示为二进制时 当两数位不同时是其异或值才为1 ,由此可得到O(n)的算法,
先将所有数存进字典树中(便于快速查询), 当用一个数去和其他数异或时,可直接根据贪心策略(尽量选不同的数位)得到最大异或值。
代码1
#include<stdio.h>
int n,m;
struct haha
{
int next[3];
int nm;
}node[100005*4];
int pos;
int makend()
{
int i;
pos++;
for(i=0;i<2;i++)
node[pos].next[i]=-1;
node[pos].nm=0;
return pos;
}
void _insert(int x)
{
int cur=0,i;
for(i=0;i<30;i++)
{
int flag=(x&(1<<i))?1:0;
if(node[cur].next[flag]==-1)
node[cur].next[flag]=makend();
cur=node[cur].next[flag];
}
node[cur].nm=x;
}
int findd(int x)
{
int cur=0,i;
for(i=0;i<30;i++)
{
int flag=(x&(1<<i))?1:0;
if(flag==1)
{
if(node[cur].next[0]!=-1)
cur=node[cur].next[0];
else cur=node[cur].next[1];
}
else if(flag==0)
{
if(node[cur].next[1]!=-1)
cur=node[cur].next[1];
else cur=node[cur].next[0];
}
}
return x^node[cur].nm;
}
int mmax(int a,int b)
{
return a>b?a:b;
}
int main()
{
int i,x;
while(scanf("%d%d",&n,&m)!=EOF)
{
int mx=0;
pos=0;
for(i=0;i<2;i++)
node[pos].next[i]=-1;
node[pos].nm=0;
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(i!=0)
mx=mmax(mx,findd(x));
_insert(x);
}
if(mx>m)
printf("YES\n");
else printf("NO\n");
}
return 0;
}
代码2
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[100005];
int main()
{
int n,m,i,j,sum,x;
while(~scanf("%d%d",&n,&m))
{
int flag = 0;
for(i = 1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
n = unique(a+1,a+n+1)-a-1;//去重并统计剩下的个数
for(i = 1; i<n; i++)
{
for(j = i+1; j<=n; j++)
{
sum = a[i]^a[j];
if(sum>m)
{
flag = 1;
break;
}
}
if(flag)
break;
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}