位操作 自然数区间取与

来源:互联网 发布:天敏t2网络机顶盒 编辑:程序博客网 时间:2024/05/16 00:30

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
原创粉丝点击