最大的位或
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1399 Accepted Submission(s): 549
Problem 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 <= 1018 。
第一行有一个正整数,表示数据的组数。
接下来每一行表示一组数据,包含两个整数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
Source
2016年中国大学生程序设计竞赛(合肥)-重现赛(感谢安徽大学)
想法:
题意要求r|k最大;其实是看k能使r的二进制从右往左的多少0变1;
首先把自然数r转化为二进制;
若r=110101;
要使r|k为110111;
则k最大为110011;
k=r-1-1;
若r=110111;
要使r|k为111111;
则k最大为101111;
k=110111-111-1;
由此可知:每次只要k满足k<=l;r的二进制从右往左的第一个0变1
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
int a[10010];
long long po(int n)
{
int i;
long long ws=1;
for(i=0;i<n;i++)
{
ws=ws*2;
}
return ws;
}
int main()
{
int N;
scanf("%d",&N);
long long l,r,Q;
while(N--)
{
memset(a,0,sizeof(a));
int i;
scanf("%lld %lld",&l,&r);
Q=r;
int n=0;
while(r>0)
{
a[n++]=(r&1);
r=r/2;
}
long long sum=0;
for(i=0;i<n;i++)
{
if(a[i]==0)
{
if((Q-sum-1)>=l)
a[i]=1;
}
else
sum+=po(i);
}
sum=0;
for(i=0;i<n;i++)
{
if(a[i])
sum+=po(i);
}
printf("%lld\n",sum);
}
return 0;
}
想法:
题意要求r|k最大;其实是看k能使r的二进制从右往左的多少0变1;
首先把自然数r转化为二进制;
若r=110101;
要使r|k为110111;
则k最大为110011;
k=r-1-1;
若r=110111;
要使r|k为111111;
则k最大为101111;
k=110111-111-1;
由此可知:每次只要k满足k<=l;r的二进制从右往左的第一个0变1
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
int a[10010];
long long po(int n)
{
int i;
long long ws=1;
for(i=0;i<n;i++)
{
ws=ws*2;
}
return ws;
}
int main()
{
int N;
scanf("%d",&N);
long long l,r,Q;
while(N--)
{
memset(a,0,sizeof(a));
int i;
scanf("%lld %lld",&l,&r);
Q=r;
int n=0;
while(r>0)
{
a[n++]=(r&1);
r=r/2;
}
long long sum=0;
for(i=0;i<n;i++)
{
if(a[i]==0)
{
if((Q-sum-1)>=l)
a[i]=1;
}
else
sum+=po(i);
}
sum=0;
for(i=0;i<n;i++)
{
if(a[i])
sum+=po(i);
}
printf("%lld\n",sum);
}
return 0;
}