题目描述
输入格式
输出格式
样例
数据范围与提示
题解
这位朋友,你看这道题这样简洁,必然是很能拓展的题啊。
首先把每个数拆分二进制,从最高位(31位)开始,往0位走,算作一个字符串,丢到Trie里。
eg:$13->$
$[1][0][1][1][0][0]..............[0][0]$
$0<------------31$
然后循环每个数。
对于一个数$x$,先拆二进制。
然后从最高位(31位)开始扫。
对于每一位,如果在Trie上对应走到了的点有与该位不同的支路(该位为0,支路为1/该位为1,支路为0),那就走。
则对答案的贡献为$(1<<i)$,所以$ans+=(1<<i)$($i$为当前位数)。
这样走出来的就是最优解了。
证明:如果在当前位能得到贡献而不走,之后就算每一位都能有贡献,$(1<<(j-1))+(1<<(j-2))+...+(1<<0) < (1<<j)$,也划不来。
所以贪心的去跑,最后得到的ans就是选这个$x$能得到的最优解了。
最后再记个max,即为答案。
1 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 2 #229998 #10050. 「一本通 2.3 例 2」The XOR Largest Pair Accepted 100 218 ms 11388 KiB C++ / 1.2 K qwerta 2018-10-15 19:38:14 3 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 using namespace std; 8 struct emm{ 9 int nxt[2]; 10 }a[3200013];//不会数数的傻子hzz一开始RE了好久qwq 11 int s[3200013]; 12 int b[37];//用来拆二进制的数组 13 int main() 14 { 15 //freopen("data9.in","r",stdin); 16 int n; 17 scanf("%d",&n); 18 int cnt=0; 19 for(int i=1;i<=n;++i) 20 { 21 //cout<<i<<endl; 22 scanf("%d",&s[i]);//读入 23 //读了就丢进Trie 24 int x=s[i],g=-1; 25 memset(b,0,sizeof(b)); 26 while(x) 27 { 28 b[++g]=x&1; 29 x>>=1; 30 } 31 int k=0; 32 for(int j=31;j>=0;--j)//从高往低建 33 { 34 if(!a[k].nxt[b[j]]) 35 a[k].nxt[b[j]]=++cnt; 36 k=a[k].nxt[b[j]]; 37 } 38 } 39 long long ans=0; 40 for(int i=1;i<=n;++i) 41 { 42 long long now=0; 43 int x=s[i],j=-1;//循环x 44 memset(b,0,sizeof(b)); 45 while(x) 46 { 47 b[++j]=x&1; 48 x>>=1; 49 } 50 int k=0; 51 for(int j=31;j>=0;--j) 52 { 53 if(a[k].nxt[1-b[j]])//尽量往不一样的去走 54 { 55 now+=(1<<j); 56 k=a[k].nxt[1-b[j]]; 57 } 58 else k=a[k].nxt[b[j]]; 59 } 60 ans=max(ans,now); 61 } 62 cout<<ans; 63 return 0; 64 }