转载于http://www.cnblogs.com/staginner/archive/2012/01/01/2309477.html
为了使最后or运算的值最大,我们不妨从二进制位的最高位开始依次考虑。如果该位是0的话,我们应该尽量让其变成1,这时我们就可以依据我们的意图算出M可能的最小值和最大值,如果这个区间和L、U这个区间有交集的话,就说明我们是可以把这一位变成1的。同理,如果该位是1的话,无论M的这位是什么,最后这位还是为1,但为了让M尽量小,我们应该尽可能让这一位为0。当然,这时你是否会怀疑这样一个问题,如果这位为0的话,相比为1就会让整体的可能值变小了,会不会后面有1位是0而我们即便该位选1都达不到下限呢?这个是不会的,因为如果该位选1都达不到下限就说明后面全部是1都达不到下限,那么只能说明在上一步的选择的时候就已经违背了规则,这样就矛盾了,所以不会出现这种情况。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
//freopen("in.txt","r",stdin);
long long int bit[34];
int num[32];
bit[0]=1;
for(int i=1; i<=32; i++)
bit[i]=bit[i-1]*2;
long long int N,L,U,aim,min,max;
int hg;
while(scanf("%lld%lld%lld",&N,&L,&U)!=EOF)
{
memset(num,0,sizeof(num));
hg=0;
while(N/2)
{
num[hg++]=N%2;
N/=2;
}
num[hg++]=N;
aim=0;
for(int i=31; i>=0; i--)
{
if(num[i]==1)
{
min=aim;
max=aim+bit[i]-1;
if(min<=U&&max>=L);
else aim+=bit[i];
}
else if(num[i]==0)
{
min=aim+bit[i];
max=aim+bit[i+1]-1;
if(min<=U&&max>=L)
aim=min;
}
}
cout<<aim<<endl;
}
return 0;
}