淺談lowbit運算


關於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也扮演着一份不可忽視的角色。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM