【链接】
【原题】
In bit-wise expression, mask is a common term. You can get a certain bit-pattern using mask. For example, if you want to make first 4 bits of a 32-bit number zero, you can use 0xFFFFFFF0 as mask and perform a bit-wise AND operation. Here you have to find such a bit-mask.
Consider you are given a 32-bit unsigned integerN. You have to find a maskMsuch thatL ≤ M ≤ UandN OR Mismaximum. For example, ifNis 100 andL= 50,U= 60 thenMwill be 59 andN OR Mwill be 127 which is maximum.If several value ofMsatisfies the same criteria then you have to print the minimum value ofM.
Input
Each input starts with 3 unsigned integersN,L,UwhereL≤U. Input is terminated by EOF.
Output
For each input, print in a line the minimum value ofM, which makesN OR Mmaximum.
Look, a brute force solution may not end within the time limit.
样例输入:
100 50 60
100 50 50
100 0 100
1 0 100
15 1 15
样例输出:
59
50
27
100
1
【题目大意】
给三个32位unsignedint数字N,L,U, 找出到一个数字M,L ≤ M ≤ U ,使得N | M(或)的结果最大,并且M最小。
【分析与总结】
由于L和U可能会相差非常大,比如L=1,U=2137384647, 直接暴力枚举的话肯定会超时的。所以需要换个方法,用贪心的思路。
为了使得N|M最大,就要使得这个结果的二进制高位尽可能的是1,所以可以用数组来模拟二进制计算。这个二进制数组的初始值等于L。
然后从高位往低位枚举,
对于第k位,如果N[k]==0,那么为了使得N的值尽量变大,就要让N[k]变为1,为了使N[k]变为1,就要让M[k]=1(使N[k]|M[k]==1),但是还要考虑M[k]变为1之后,M的新值是否>U,如果大于U的话就不能让M[k]变为1了。
如果N[k]已经等于1了, 那么就没有必要让M[k]也是1了(因为1|0==1)。那么M[k]如果是0就不管继续枚举下去,如果M[k]是1,就尝试是否可以把M[k]变为0,如果变为0之后还满足M二进制数组的值>=L的话,就可以变为0(因为使得M尽量地小).
最终得到的M数组表示的值就是答案了。
【代码】
/* * UVa: 10718 - Bit Mask * Type: Greedy * Result: Accept * Time: 0.012s * Author: D_Double * */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; long long N,L,U; bool bit[32], tmp[32]; inline long long getValue(){ long long ans=0, U=1; for(int i=31; i>=0; --i)if(bit[i]){ ans += U<<(31-i); } return ans; } long long solve(){ memset(bit, 0, sizeof(bit)); for(int i=0; i<32; ++i) bit[i] = L>>(31-i)&1; for(int i=31; i>=0; --i){ if((N >> i & 1)==0 && bit[31-i]==false){ bit[31-i]=true; memcpy(tmp, bit, sizeof(bit)); int j=31-i+1; bool flag=false; while(j<=32){ if(getValue()<=U){ flag=true; break; } while(bit[j]==false && j<32)++j; if(j==32)break; bit[j] = false; } if(!flag){ memcpy(bit, tmp, sizeof(tmp)); bit[31-i] = false; } } else if((N>>i&1)==1&&bit[31-i]==true){ bit[31-i] = false; if(getValue() < L) bit[31-i] = true; } } return getValue(); } int main(){ while(scanf("%lld%lld%lld",&N,&L,&U)!=EOF){ long long ans=solve(); printf("%lld\n", ans); } return 0; }
—— 生命的意义,在于赋予它意义。
原创http://blog.csdn.net/shuangde800,By D_Double (转载请标明)