想了好长时间,实在做不出来了,上网参考了一下大牛的题解。
题目大意:
给定3个数,N,U,L,求在【U,L】 区间内的一个数M ,使得N | M的值最大。
大体思路:
将给定的数N 转化成为2进制
之后从高位向地位一位一位的判断
1、如果这位是0的话,那么要使这一位变成1,既然这样,那么假定这一位变成了1,之后看,这位为1之后的最大最小值是否和给定的区间有交集,如果有的话说明可以变。
2、如果这位是1的话,那么为了使输出结果尽量的小,就要求这一位最好为0,那么就和上面一样,判断,如果这一位是0的话,他的最大最小值是否在区间内,如果在的话就可以取到0,否则的话只能取1了。
总结:感觉是贪心的思路,不过没做出的原因是无法判断变化位数之后,该数是否在区间范围内,还有注意long long 的使用
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXD 100 + 10
#define max(a,b) (a > b ? a : b)
using namespace std;
typedef long long LL;
LL N,M,R,L;
LL b[MAXD];
void biao(){
b[0] = 1;
for(int i = 1 ; i <= 32 ; i++)
b[i] = b[i - 1] * 2;
return ;
}
int solve(){
int x[MAXD] = {0};
int size = 0;
LL ans = 0;
while(N){
x[size++] = N % 2;
N /= 2;
}
for(int i = 31 ; i >= 0 ; i --){
if(x[i] == 0){
LL p = ans + b[i]; /*如果这位取1的最小值*/
LL q = ans + b[i + 1] - 1; /*如果这位取1的最大值*/
if(p <= R && q >= L)
ans += b[i];
}
else{
LL p = ans; /*如果这位取0最小值*/
LL q = ans + b[i] - 1; /*如果这位取0最大值*/
if(q < L || p > R) /*如果这个区间不能满足*/
ans += b[i];
}
}
printf("%lld\n",ans);
}
int main(){
biao();
while(scanf("%lld%lld%lld",&N,&L,&R) != EOF){
solve();
}
return 0;
}