UVa 10718 - Bit Mask

【链接】

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=113&page=show_problem&problem=1659


【原题】

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 integer N. You have to find a mask M such that L ≤ M ≤ U and N OR M is maximum. For example, if is 100 and L = 50, U = 60 then M will be 59 and N OR M will be 127 which is maximumIf several value of M satisfies the same criteria then you have to print the minimum value of M.

Input
Each input starts with 3 unsigned integers NLU where L ≤ U. Input is terminated by EOF.

Output
For each input, print in a line the minimum value of M, which makes N OR M maximum.

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  (转载请标明)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值