最大的位或
Description
B君和G君聊天的时候想到了如下的问题。
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。
其中|表示按位或,即C、 C++、 Java中的|运算。
给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大。
其中|表示按位或,即C、 C++、 Java中的|运算。
Input
包含至多10001组测试数据。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数 l,r。保证 0 <= l <= r <= 10^18。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数 l,r。保证 0 <= l <= r <= 10^18。
Output
对于每组数据输出一行,表示最大的位或。
思路:
l<r,化为二进制有两种情况:1.L和R等长。2.L长度小于R。
情况2是我很乐意见到的,因为我可以取到一个与L同位数但全为1而且一定小于R的L1.
因此对于情况1,我们很乐意从L的某一位置开始发现满足情况2。
代码:
#include<stdio.h>
int memlength(long long n) //十进制转化为二进制
{
int flag=0;
while(n)
{
n/=2;
flag++;
}
return flag;
}
int main()
{
int n;
int a[100000]={0},b[100000]={0};
scanf("%d",&n);
while(n--)
{
long long l,r,L,R;
scanf("%lld",&L);
scanf("%lld",&R);
l=L;
r=R;
int length=memlength(L);
for(int i=1;i<=length;i++)
{
a[i]=l%2;
l=l/2;
}
length=memlength(R);
for(int i=1;i<=length;i++)
{
b[i]=r%2;
r=r/2;
}
if(memlength(R)>memlength(L)) //情况2
for(int i=memlength(R);i>=1;i--)
{
b[i]=1;
}
else if(memlength(R)==memlength(L)) //情况1
{
int i=memlength(R);
while(a[i]==b[i])
i--; //从这个位置a[i]!=b[i]而且一定是a[i]=0,b[i]=1
for(i;i>=1;i--)
{
b[i]=1; //之后所有b[i]都有办法取到1 ^_^
}
}
long long sum=0;
for(int i=memlength(R);i>=1;i--)
{
sum*=2;
if(b[i])
sum+=2;
}
printf("%lld\n",sum/2);
}
return 0;
}