转载自: https://blog.csdn.net/qq_40508713/article/details/81387034
## 最大的位或 HDU - 5969 ##
B君和G君聊天的时候想到了如下的问题。
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。
其中|表示按位或,即C、 C++、 Java中的|运算。
Input
包含至多10001组测试数据。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数l,r。
保证 0 <= l <= r <= 1018。
Output
对于每组数据输出一行,表示最大的位或。
Sample Input
5
1 10
0 1
1023 1024
233 322
1000000000000000000 1000000000000000000
Sample Output
15
1
2047
511
1000000000000000000
刚开始做这个题的时候通过观察发现对于第一组样例,将其转换为二进制后
R 10———->1010
15———->1111
根据题目要求可以利用异或反推出 x=5 5|10 = 15
5————>0101
由此我猜了一下可以将右边界转为二进制后找到最高位的1然后将最高位后所有0变为1
然后wa了
重新整理后发现
L 100——–>0110 0100
R 101——–>0110 0101
如果按照以上规律求得的res = 0111 1111 = 127
根据题目要求可以利用异或反推出 x=26 超出了左边界,所以不能直接用这个规律。
那么根据上面的推导可以得出以下结论:要找到左右边界二进制下最高不同位,将此后所有位标为1。
这里使用了STL中的bitset,bitset是用来进行一些状态储存的操作。类似于一个标记数组,又类似于状压里面的二进制。bitset可以访问指定下标的bit位。
所以我们可以通过遍历找到最高不同位的下标,用(1LL << 下表)求得X的值
需要调用bitset库。
- 一些常用操作
- 进行一些与二进制相同的操作
- b<<1;//b整体左移
- b|=10; //b或 101
其他操作请移步bitset总结
#include <iostream>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int main()
{
int t;
ull x,y;
cin >> t;
while(t--){
cin >> x>>y;
bitset<200> w (x^y);
int i = 199;
while(w[i]!=1&& i>=1) i--;//找到最高位不相等的第一位
ull a = (1LL<<i)-1;
cout << (y|a) <<endl;
}
return 0;
}
(还是觉得这么写很牛逼hhh,stl大法好)