关于lowbit运算的相关知识

本篇随笔简单讲解一下计算机中位运算的一类重要运算方式——\(lowbit\)运算。

lowbit的概念

我们知道,任何一个正整数都可以被表示成一个二进制数。如:

\[(2)_{10}=(10)_2
\]

\[(4)_{10}=(100)_2
\]

\[\cdots
\]

那么定义一个函数\(f=lowbit(x)\),这个函数的值是\(x\)的二进制表达式中最低位的\(1\)所对应的值。

比如:

\[(6)_{10}=(110)_2
\]

那么\(lowbit(6)\)就等于\(2\),因为\((110)_2\)中最低位(就是从右往左数的第二位)对应的数是\(2^1=2\)

所以假设一个数的二进制最低位的\(1\)在从右往左数的第\(k\)位,那么它的\(lowbit\)值就是

\[2^{k-1}
\]

lowbit函数的实现

lowbit函数实现有两种方式:

一、

x&(x^(x-1))

二、

x&-x

简单解释一下:

我们得到lowbit的值,只需要得到最后一个1的位置,并且把除了这个位置之外的所有位置全部置成零。然后输出就可以。

那么我们看一看x&(x^(x-1))

拿上面的6举例:

\[(110)_2-1=(101)_2
\]

我们发现,根据小学数学减法运算的借位原则(滑稽),对一个二进制数进行减1,那么会出现从这个这个数的最后一个1开始到最后的所有数都取反,即构成一个\(01111\cdots\)的串。

我们把这个数与原数异或,就会造成:第一个1以后的数(包括第一个1)全部取1.其他的位全部取0.即构成一个由一堆0后面跟一堆1的串。

那么再把原式做一个与运算,那么除了原来的那个1(对应位都是1)为1,其他位全是0,完成任务。

那么我们再看一看x&-x

根据计算机补码的性质。

补码就是原码的反码加一

如:

\[(110)_2=6
\]

反码:

\[(001)_2
\]

加一:

\[(010)_2
\]

可以发现变为反码后 x 与反码数字位每一位都不同, 所以当反码加1后神奇的事情发生了,反码会逢1一直进位直到遇到0,且这个0变成了1,所以这个数最后面构造了一个 100… 串。 由于是反码,进位之后由于1的作用使进位的部分全部取反及与原码相同,所以可以发现 lowbit 以前的部分 x 与其补码即 -x 相反, lowbit x 与 -x 都是1,lowbit 以后 x 与 -x 都是0 所以 x&-x 后除了 lowbit 位是1,其余位都是0。符合条件。

用lowbit运算统计1的个数

我们可以使用lowbit运算统计一个整数的二进制形式下1的个数。

实现原理很简单啦,就是:我们先用lowbit运算找出\(lowbit(x)\),然后用原数减去这个数,依次循环,直到为0为止。

这也是树状数组的实现原理。

代码:

while(x)
{
x-=x&-x;
ans++;
}

(巨短无比)

lowbit运算的应用

关于lowbit运算,最著名的应用应该算是树状数组。但是lowbit的神妙远远不止树状数组,在很多二进制和位运算的相关题目中,都有lowbit运算的影子。甚至,在状态压缩DP中,lowbit也扮演着一份不可忽视的角色。

最新文章

  1. Flatten Binary Tree to Linked List [LeetCode]
  2. linux-shell编程笔记01
  3. java.io.IOException: Timed out waiting 20000ms for a quorum of nodes to respond
  4. Kafka Producer相关代码分析【转】
  5. php超全局数组变量
  6. redis与memcached比较
  7. Python可以做什么?
  8. cellspacing与cellpadding
  9. 稍加详细的ATR信息,将完善历史字节部分+
  10. Firebug 非常好用
  11. JMeter中BeanShell的实际应用
  12. Mac 启动或者禁用翻盖自动开关机
  13. SVD(奇异值分解)小结
  14. Ubuntu安装Apache+PHP
  15. Java double 精度
  16. supervisor - Python进程管理工具(转)
  17. d3js enter/exit深入了解
  18. zookeeper报错 JAVA_HOME is not set
  19. H5移动端视频问题(苹果全屏播放问题等)
  20. NOIP2013 D1 T3 货车运输

热门文章

  1. Codeforces Round #593 (Div. 2)
  2. acwing 17. 从尾到头打印链表
  3. 【Oracle】SQL的一些关键字
  4. 【LOJ6397】「THUPC2018」蛋糕 / Cake(搜索)
  5. Unity BehaviorDesigner行为树基础总结
  6. Shell脚本中的while getopts用法小结
  7. Zookeeper学习记录及Java客户端连接示例
  8. 杂牌机搞机之旅最终章————刷入Xposed框架
  9. Python线程与进程 I/O多路复用
  10. django中're_path'的用法