位运算最常用的两种操作
看 n 的第 k 位数字是几
一个整数 n, 其二进制表示中第 k 位数字是几, k从 0 开始计数
n=15 ==> n=(1111)~2~
①先把第 k 位移到最后一位: n » k
②看个位是几, 公式是$x&1$
结合①②, 可得要求 n 的二进制第 k 位的公式为: $n » k ;& 1$
对于一个十进制数x, 如果我们从最高位(比如 32 位, 从 k=32)开始打印这个数,那么打印完之后得到的就是x 的二进制表示
lowbit–树状数组基本操作
lowbit(x) : 返回 x 的最后一位 1和后面的二进制数
举例
lowbit(1010~2~) = 10
lowbit(1000~2~) = 1000
lowbit实现方式
$x & -x$
在 c++中, 一个整数的负数是原数的补码(补码是取反加一), 所以 -x 的二进制表示和 ~x+1( x取反加一)的二进制表示是一样的
∵-x = ~x+1
∴x&-x ==> x&(~x+1)
推导过程:
![lowbit 推导过程](lowbit 推导过程.jpeg)
~
表示取反
应用
-
求 x 里面 1的个数
每次将 x 中的 最后一个 1 减去, 直到x 变为 0, 我们记录减了几次, 就可以知道有多少个 1
原码,反码,补码
令 x=1010~2~ 假设是 32 位整数
原码: 0000…..01010
反码: 0111…..10101 原码除符号位外取反
补码: 0111…..10110 反码加一 ~x+1
为什么要有补码?
因为在计算机里面没有减法, 需要用加法来做减法
一个x 加上他的相反数-x 应该等于 0: x+(-x)=0
那么有如下推导
$(-x) = 0-x\(-x)=(32个 0)_2 - x\此时做减法,32个 0 会往前借一位,也就是\(-x)=(1+后面32个 0)-x\此时\(1+后面32 个 0)-x = \sim{x} + 1\故\减法用\sim{x+1}这个补码表示$
正数和零的原码表示和补码表示是一样的, 不需要专门求补码, 直接用原码表示