📜  在二进制表示中 LSB 为 0 的范围 [L, R] 中的数字计数(1)

📅  最后修改于: 2023-12-03 15:23:29.462000             🧑  作者: Mango

计算二进制表示中 LSB 为 0 的范围 [L, R] 中的数字个数

在二进制表示中,LSB(Least Significant Bit)指最低有效位,即最右边的位。本文介绍如何计算一个区间 [L, R] 中二进制表示中 LSB 为 0 的数字个数。

思路

对于一个二进制数,如果它的 LSB 为 1,则将它减去 1 会使得它的 LSB 变成 0,并且更高位的数字都变成了反码(即 0 变成 1,1 变成 0)。例如,1011 - 1 = 1010,1100 - 1 = 1011。

根据这个规律,如果将一个数减去 1,并将它和原数做 &(按位与)运算,会把它的 LSB 以及所有比它更低的位都变成 0。例如,1011 & 1010 = 1010,1100 & 1011 = 1000。

因此,如果我们将一个数字 x 和它的 x - 1 做 & 运算,再统计有多少个数字 y 满足 y & (y-1) == 0,则 y 的二进制表示中 LSB 为 0。那么在区间 [L, R] 中满足条件的数字个数就是 f(R) - f(L-1),其中 f(x) 表示小于等于 x 的数字中,满足 y & (y-1) == 0 的数字个数。

代码示例
def count_lsb_zero_numbers(L, R):
    def count_lsb_zero(n):
        cnt = 0
        while n > 0:
            n &= n - 1
            cnt += 1
        return cnt

    def count_f(x):
        res = 0
        for i in range(1, 32):
            res += x // (1 << i) * (1 << (i - 1))
            res += max(0, (x % (1 << i)) - (1 << (i - 1)) + 1)
        return res

    return count_f(R) - count_f(L-1)

print(count_lsb_zero_numbers(3, 10))  # 输出 6,满足条件的数字为 4、5、6、8、9、10

以上是 Python 代码示例,实现了计算 [L, R] 区间中二进制表示中 LSB 为 0 的数字个数的函数。其中 count_lsb_zero 函数用于计算一个数的二进制表示中 1 的个数, count_f 函数用于计算小于等于 x 的数字中,满足 y & (y-1) == 0 的数字个数,最后将区间 [L, R] 分别代入 count_f 函数即可得到答案。