lowbit运算, 求二进制数中"1"的个数

lowbit运算

$ lowbit(n) $定义为非负整数$ n $在二进制表示下最低位的"1"及其后面的所有"0"构成的数值

如当$ n = 10 $, 其二进制表示为$ (1010) $, 则$ lowbit(10) = 2 = (10) $

 

$ lowbit(n) $的公式推导

设整数 $n$ 的二进制表示为 $n =\,...1000...$(往后都是0), 最低位的"1"位第 $k$ 位

则 $-n$ 的二进制表示为  $-n =\,...1111... $(往后都是1),  (即$n$ 按位取反后加一), 其中 $-n$ 的第 $k$ 位仍是1, 但是其余位置都取反
则$n$ & $-n$ 可以表示最低位的"1"表示的二的次幂, 即 $ lowbit(n) = n $ & $-n$

 

查询lowbit(n)对应的二进制数中的位, 即计算 $ log_{2}^{lowbit(n)} $

建立一个数组 $ H[\, 1 << 20\, ] $ 来存储 $log$, 令 $ H[\, 2^{k}\, ] = k $

for(int i = 0; i < 20; i++) H[1 << i] = i;      //预处理

*更高效, 节省空间的方法, 开 $H[\, 37\, ] $, 且令$ H[\, 2^{k}\, mod\, 37\, ] = k $

*原因: 当 $k$ 在0 ~ 35之间时, $ 2^{k}\, mod\, 37$ 的值各不相同, 且取遍了整数1 ~ 36

for(int i = 0; i < 36; i++) H[(1ll << i) mod 37] = k    //1ll表示(long long 1), 左移的优先级低于取模

 

计算二进制数中"1"的个数

即遍历 $n$ 中是"1"的位置, 每轮迭代 $ n\, -= lowbit(n)$, 时间复杂度与1的个数同级

//lowbit运算
int lowbit(int x) {
    return x & -x;
}

//计数
int count(int n) {
    int cnt = 0;
    while(n) cnt++, n -= lowbit(n);
    return cnt;
}

 

posted @ 2020-10-06 13:13  yikanji  阅读(268)  评论(0)    收藏  举报