位操作 自然数区间取与

hackerank and-product题目

给定一个自然数区间[a, b],对区间里的所有自然数取与。

输入:8 13
计算:8 & 9 & 10 & 11 & 12 & 13 的结果并输出

介绍一个很简单的O(log(b - a))复杂度的算法:

假设a = 10, b = 13

10 的二进制是 01010
11 的二进制是 01011
12 的二进制是 01100
13 的二进制是 01101

从a递增到b,二进制的变化经过了01100(即12),任何该区间的自然数与12取与首先就会导致结果最后两位为0。然后,因为a和b第3位分别是0和1,取与会导致第3位结果为0。

所以对于一般情况可以这样做:
(1)取b的位长 bit_len
(2)从高位开始检查a和b 同一二进制位是否同为1或0
(3)如果遇到 第k位(从低位算起) 不同,且肯定是a该位为0,b该位为1(因为b>a),从之前你的例子可以看到从a递增到b必定会经过 1000….0(2的k-1次方),与 2的k-1次方 取与会导致结果的 低k-1位 全为0, 且 第k位 也为0
(4)所以最终的结果是 高(bit_len - k)位等于a的高(bit_len - k)位, 低k位全为0

代码如下:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;


int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int num_case, order;
    long long a, b;
    scanf("%d", &num_case);
    while(num_case--){
        scanf("%llu%llu",&a,&b);
        order = (int)(log(b) / log(2));
        while( ( (a >> order) & 0x01 ) == ( (b >> order) & 0x01 ) ){
            order--;
        }
        printf("%llu\n", (a >> order) << order);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值