UVA_10718
为了使最后or运算的值最大,我们不妨从二进制位的最高位开始依次考虑。如果该位是0的话,我们应该尽量让其变成1,这时我们就可以依据我们的意图算出M可能的最小值和最大值,如果这个区间和L、U这个区间有交集的话,就说明我们是可以把这一位变成1的。同理,如果该位是1的话,无论M的这位是什么,最后这位还是为1,但为了让M尽量小,我们应该尽可能让这一位为0。当然,这时你是否会怀疑这样一个问题,如果这位为0的话,相比为1就会让整体的可能值变小了,会不会后面有1位是0而我们即便该位选1都达不到下限呢?这个是不会的,因为如果该位选1都达不到下限就说明后面全部是1都达不到下限,那么只能说明在上一步的选择的时候就已经违背了规则,这样就矛盾了,所以不会出现这种情况。
#include<stdio.h>
#include<string.h>
long long int N, L, R, d[64];
int a[64];
void prepare()
{
int i;
d[0] = 1;
for(i = 1; i <= 32; i ++)
d[i] = d[i - 1] * 2;
}
void solve()
{
int i, j, k;
long long int x, y, ans = 0;
for(i = 0; i < 32; i ++)
{
a[i] = N % 2;
N /= 2;
}
for(i = 31; i >= 0; i --)
{
if(a[i] == 0)
{
x = ans + d[i];
y = ans + d[i + 1] - 1;
if(x <= R && y >= L)
ans += d[i];
}
else
{
x = ans;
y = ans + d[i] - 1;
if(x > R || y < L)
ans += d[i];
}
}
printf("%lld\n", ans);
}
int main()
{
prepare();
while(scanf("%lld%lld%lld", &N, &L, & R) == 3)
{
solve();
}
return 0;
}