二進位制位運算在演算法中的巧妙運用

2021-06-14 06:25:22 字數 2029 閱讀 6034

#include using namespace std;

bool is_pow2(int x) //判斷是否2的n次方

void binary(int num)//十進位制轉二進位制

while(--i)

對集合的表示

大多數時候,我們可以用乙個整數來表示乙個包含不超過32(當然如果使用64位整型變數也可以是64個)個元素的集合——對於每乙個位,如果元素為1,則表示存在當前位所對應的集合成員,如果是0,則表示這個集合成員是不存在的。

比如a=1011 就可以表示集合,而上面提到的1<

下面我們就能推導出一些直觀的集合運算。

我們定義 all_bits 為全集即各二進位制位均為1的數。

集合的並 a|b

集合的交 a&b

集合的差 a& ~b

補集      all_bits^a

新增特定元素bit a|=1<

清除特定元素bit a^=1<

取出特定元素bit a&=1<

判斷是否存在特定元素bit (a&1<

列舉子集

當乙個數的二進位制表示乙個集合的時候,位運算的乙個巨大優點在於其可以非常輕鬆和高效地列舉當前集合的所有子集。

它的性質在於——如果a是b的真子集,那麼可以保證列舉a子集的次數一定小於列舉b的子集的次數。這一點可以大大

提高很多壓位動態規劃題目的實現效率。

(1)暴力的方式

最暴力的方式莫過於列舉所有可能的集合,然後一一判斷是否為當前集合的子集。

如果需要列舉的集合是n個元素的集合,那麼對所有可能集合都進行一次列舉操作,花費的時間為o((2n)2)=o(4n)。

(2)高效的方式

假設全集有n個元素,那麼所有可能的集合就有2n個,對於任意子集s,用n位2進製簡單列舉s的所有子集,個數就有2n個,

因此如果對所有集合都進行這樣一次列舉操作,那麼總的時間複雜度就是o((2n)2)=o(4n)。高效的方式。

這裡的技巧和低位技術的技巧是類似的——當我們取出最後乙個1的時候,這個1將變成0,而比其低位的0將變成1。

與低位技術不同的是,我們並不是要提出某一位1,而是要去除某一位的1,並補上一些我們需要的1。

所以假設當前集合為superset,那麼列舉的**段則為

iterating_all_subset(superset)

若當前為n位二進位制的集合,並且對所有可行集合進行上述操作,可以證明,操作的總次數為o(3n)。

有趣的技巧

再提一些在c/c++中更加驚人的位運算技巧——它絕對可以讓你在同學面前炫耀一下。

1.計算絕對值

abs( x )

這裡需要注意的是,上面的x, y 預設為32位有符號整數。

2.按位翻轉

x=((x&0xaaaaaaaa)>>1)|((x&0x55555555)<<1);

x=((x&0xcccccccc)>>2)|((x&0x33333333)<<2);

x=((x&0xf0f0f0f0)>>4)|((x&0x0f0f0f0f)<<4);

x=((x&0xff00ff00)>>8)|((x&0x00ff00ff)<<8);

x=((x&0xffff0000)>>16)|((x&0x0000ffff)<<16);

如果無符號32位整數x=311=(100110111)2,那麼經過上述操作後x=3967811584=(11101100100000000000000000000000)2。

這裡不多作解釋(其實研讀這段**是很有意思的一件事情),留給有興趣的讀者思考。

3.列舉恰好含有k個元素的集合

我們假設全集為含有n個元素為 ,那麼**段可以寫成:

int s = (1 << k) - 1;

while (!(s & 1 << n))

當然最後一句話也可以寫成s |= (lz >> __builtin_ctz(lo << 1)) – 1來避免除法運算。

二進位制位運算

與運算,6 3 2 或運算 6 3 7 異或運算 6 3 5 反碼 6 7 左移 3 2 12 3 2 2 12 右移 3 1 1 3 2 1 無符號右移 3 1 1 3 2 1 按位與,當兩位同時為1時才為1如 1 1 1 1 0 0 0 1 0 6 3相當於 0110 0011 0010 2 按...

二進位制位運算

一 按位與 位全為1,結果才為1 0 0 0 0 1 0 1 0 0 1 1 1 特殊用法 清零。如果想將乙個單元清零,就是使其全部二進位制位為0,只要與乙個各位都為零的數值相與,結果為零 取乙個數中的指定位。如x 10101110要取x的低4位,用x 00001111 00001110即可 二 按...

二進位制的位運算

按位與 兩位全為1,結果為1 特殊用途 1 清零,想要將乙個單位清零,只要與乙個各位都為零的數值相與,結果為零 2 去乙個數中的指定位 如 x 10101110,取x的低四位用x 0000 1111 0000 1110即可得到 方法 找到乙個數,對應x要取的位,該數的對應位為1,其餘位為0,用此數與...