题目大意:给一数N,在区间[L, U]上找到一个数M使得M| N的值最大,如果有M有多个可能值,取最小的那个值。
从最高位开始逐位判断,如果N的该位为0,为使M | N的值最大,M的该位应考虑置为1,然后判断M的该位为1时的可能取值区间[lmin, lmax],如果区间[lmin, lmax]与区间[L, U]有交集,则说明该位可置为1;如果N的该位为1,为使M的值尽可能小,M的该位应考虑置为0,然后判断可能取值区间与[L, U]是否有交集,如果没有交集,该位置为1。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 3 int main() 4 { 5 #ifdef LOCAL 6 freopen("in", "r", stdin); 7 #endif 8 long long d[35]; 9 d[0] = 1; 10 for (int i = 1; i <= 32; i++) 11 d[i] = d[i-1] * 2; 12 long long N, L, U; 13 while (scanf("%lld%lld%lld", &N, &L, &U) != EOF) 14 { 15 int a[32] = {0}; 16 for (int i = 0; N > 0; i++) 17 { 18 a[i] = N % 2; 19 N /= 2; 20 } 21 long long lmax, lmin, ans = 0; 22 for (int i = 31; i >= 0; i--) 23 { 24 if (a[i] == 0) 25 { 26 lmin = ans + d[i]; 27 lmax = ans + d[i+1] - 1; 28 if (lmin <= U && lmax >= L) 29 ans += d[i]; 30 } 31 else 32 { 33 lmin = ans; 34 lmax = ans + d[i] -1; 35 if (lmax < L || lmin > U) 36 ans += d[i]; 37 } 38 } 39 printf("%lld ", ans); 40 } 41 return 0; 42 }
开始用位移操作,可是总是出现错误,应该是类型范围的问题吧,这方面很弱,感觉这些东西不怎么用,而且有点枯燥,就没怎么看过,即使看也是大概看看,没好好研究,还是要抽时间看一下的(话说,我现在感觉还是用的不多,不过,遇到问题就完蛋了...)