HDU - 5969(位运算)

题目链接:HDU - 5969

 

题意:找出区间[L, R]中的两个数x、y,使x|y(位或)最大。

 

题解:位或是二进制运算,二进制中只有0和1,要使位或最大,就要使R位或后的1尽可能的多。因为位或的性质,不可能位或后使数的最高位大于R。所以其中一个数必须是R。首先要知道,在剩下的数中能使R增加的1的位数是有限的。那么能增加多少呢?能使L与R出现的L的最高不同位之后的低位全部变成1。

      例:R:10100010       能产生最大位或的数:R:10100010     位或结果:10111111

             L:10011000                                         x:10011111

         可以将上面R的绿色位全部变成1。

这是因为一个数x从L开始增大到R,x与R出现的x的最高不同位不能超过L与R的L的最高不同位。如样例中x与R最高不同位不能超过红色位。因为能产生最的位或的x必须满足与R的最高不同位之后的位全部是1,如紫色的部分,这样位或后能使R的相同部分全变成1,而如果此时让紫色位1继续增多,那么会使x大于R,不满足条件。

操作:

1.取K = R ^ L;这样能将R与L所有不同的位都标记出来。例中的K = 00111010

2.求出求出K的最高位的位数d(例K的蓝色位),令x = (1 << d) - 1。这样能使最高不同位后的位全部变成1。例中的x = 00011111

3.ans = R | x

 

 

#include <bits/stdc++.h>
using namespace std;

//求出最高位
int digit(long long K)
{
    int d = 0;
    while(K > 0){
        K >>= 1;
        d++;
    }
    return d;
}

int main()
{
    int T;
    long long L, R, ans, K, x, d;
    scanf("%d", &T);
    while(T--){
        scanf("%I64d%I64d", &L, &R);
        K = R ^ L;
        d = digit(K);
        x = (1LL << d) - 1;
        printf("%I64d\n", R | x);
    }
    return 0;
}

 

 

 

 

 

 

 

         

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值