题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1472
题目思路:异或是啥呀?
异或就是把两个数字变成位数相同的二进制在同位比较,相同为0,不同为1,如:
011
100
——
111
所以 3 XOR 4 == 7
那让我们找异或不就是说把一大堆二进制的字符串存起来找嘛
那基本思路就出来了,将数字转变成由 0 和 1组成的字符串,然后找不同
字符串?找不同?那不就是把字典树糊人脸上了嘛
所以这个程序的非主体部分就白给了:
一个是主程序,输入 n,输入 n 个 x,存起来
一个是存储,用 (x>>k)&1 把每一位倒腾出来再用字典树的方式存储
注意!异或的解释里有“位数相同”这几个字
所以要在前面用 0 补齐,它说了“小于 2^31 "和“小于 10^5 ”,所以横坐标开到 32*100000+1 就足够
接下来就是程序的主体部分:搜索,我应该如何找到那两个凑起来最大的串串呢
首先我可以先敲定一个字符串,然后再上树里找去
但是那两个答案串本就无法确定,那直接一个一个定得了
所以在主程序里面每存一个 x 就要假定这个 x 为其中一个答案串去寻找
还是用 (x>>k)&1 把每一位倒腾出来然后一位一位搞
如果说它的对位,也就是那个存 !((x>>k)&1) 的地方有东西
也就是说平白无故多个1出来
行了,把 1 以正确的位置存进ans(即 k ),然后那个我们对位的串就是第二个答案串了
凑凑凑出来一个 ans,打回去,和其他的一众 ans 比比,找那个“力拔山兮气盖世”的
最后输出
注意!从最高位开始,性价比最高
#include<bits/stdc++.h>
using namespace std;
int trie[3200001][3],tot=1,ans=-10000,n,x,i;
void putin(int x){
int p=1,k,t;
for(k=30;k>=0;k--){
//注意,从最高位开始
t=(x>>k)&1;//把每一位导出来
if(trie[p][t]==0){
trie[p][t]=(++tot);
}
p=trie[p][t];
}//以字典树的方式存储
}
int finding(int x){//核心程序
int ans=0,p=1,k;
//ans初始值必须等于0
//不然出来什么“野1”不好解释
for(k=30;k>=0;k--){
//注意,从最高位开始
int t=(x>>k)&1;//一位一位导
if(trie[p][!t]){
//对位有人
ans=ans|(1<<k);
//按正确的位置存1
p=trie[p][!t];
//将其视为第二个答案串
}
else{//什么?难办?
p=trie[p][t];
//那就别办了
}
}
return ans;//打回去
}
int main(){
scanf("%d",&n);//n
for(i=0;i<n;++i){//n个数字
scanf("%d",&x);//输进去
putin(x);//存了它
ans=max(ans,finding(x));
//找那个最大的
}
printf("%d",ans);//打出来
return 0;
}
题目总结:新知识点:看到位运算可以往字符串方面想想
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】