树状数组lowbit()函数所求的就是最低位1的位置所以可以通过位运算来计算
树状数组通过 x&(x^(x-1)) 能够成功求出lowbit的原因:
首先设x=6,即110(2) 于是我们使 x-1=101 可以发现,当我们将一个二进制数减一时,从最低位一(即lowbit)开始向后的部分与之前全部相反,因为减去的1对后面的每一位都有影响,同时因为是二进制,影响就是让每一位都取反了
110
101
从最低位一(第二位)开始向后全部相反了 所以我们再与 x 异或一发,那么从lowbit开始往后全是1
110^101=011
然后我们再用x与新数按位与一下 因为 x lowbit 以前的部分是1或0,lowbit 是1,之后的部分都是0,新数 lowbit 之前的部分都是0,lowbit 是1,之后的部分都是1 所以与完之后他们的交集就是 lowbit
110&011=010
而 lowbit 的常用计算方法是 x&-x ,其原理与上面的方法不尽相同 这个式子运用了计算机的补码计算原理 补码计算简单来讲就是原码的反码反加一 如:
0110(2)=6
变为反码后为 0001
再加一为 0010 即它的补码
可以发现变为反码后 x 与反码数字位每一位都不同, 所以当反码加1后神奇的事情发生了,反码会逢1一直进位直到遇到0,且这个0变成了1,所以这个数最后面出现了一个 100… 串。 由于是反码,进位之后由于1的作用使进位的部分全部取反及与原码相同,所以可以发现 lowbit 以前的部分 x 与其补码即 -x 相反, lowbit x 与 -x 都是1,lowbit 以后 x 与 -x 都是0 所以 x&-x 后除了 lowbit 位是1,其余位都是0