88888888y

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
统计
 

题目: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;
}

题目总结:新知识点:看到位运算可以往字符串方面想想
posted on   88888888y  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
 
点击右上角即可分享
微信分享提示