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;
}

浙公网安备 33010602011771号