题意:
给出区间 [ L , R ] ,在区间取两个数使它们位或值最大,输出这个最大值。( 0 <= L <= R <= 1e18 )
思路:
我们假设 L = 1001011001 ,R = 1001101010 ;我们可以看到 L 和 R 都有10位并且前四位相同;
然后我们有一种想法:因为 R >= L 所以从左往右数,直到他们有一位不相同(红色部分),那么必有—— R 的这一位为 1 ,L 的这一位必为 0 (因为 R>=L )。
如上面的例子,L和R从左到右到第五位不同,那么有数值: A = 1001011111 B = 1001100000
A和B必定在 [ L, R ] 区间内,而: A | B = 1001111111 , 所以我们可以知道从红色部分 (L和R从左到右出现不相等的第一位) 开始,后面的位都可以取到 1 前面的位因为都相等,所以不能改变。
同样如果 L = 0001011001 , R = 1001101010 (L 的位数比 R 少)情况也是一样的,就相当于第一位就不相同 ,那么: A = 0111111111 B = 1000000000
这两个数也必定在[ L, R ] 区间内, A | B = 1111111111 ;
代码:
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long Lint;
const Lint one=1;
int t;
int main(){
Lint l,r;
cin>>t;
while(t--){
scanf("%lld%lld",&l,&r);
for(int i=62;i>=0;i--){
Lint t1 = l & (one<<i); // l 的第 i 位(从左到右)
Lint t2 = r & (one<<i); // r 的第 i 位(从左到右)
if(t1^t2){
for(int j=0;j<=i;j++)
r=r|(one<<j); //将 r 后 i 位全部置 1
break;
}
}
cout<<r<<endl;
}
return 0;
}