More Related Content More from Wei Luan Wang (6) Bit Hack4. AND
• int a = 3 = 011 2
int b = 5 = 101 2
• a & b = 1 = 001 2
011
& 101
--------
= 001
5. OR
• int a = 3 = 011 2
int b = 5 = 101 2
• a | b = 7 = 111 2
011
| 101
--------
= 111
6. XOR (Exclusive OR)
• int a = 3 = 011 2
int b = 5 = 101 2
• a ^ b = 6 = 110 2
011
^ 101
--------
= 110
10. 正負號
• 正:0 負:-1
int sign = a >> 31;
• 正:1 負:-1
int sign = 1 | ( a >> 31 );
• 正:1 零:0 負:-1
int sign = ( a != 0 ) | ( a >> 31 );
12. 是不是 2 的冪次
• 例子:8 ⇒ 𝑦𝑒𝑠 , 7 ⇒ 𝑛𝑜
• 正整數
bool result = ( a & ( a – 1 ) ) == 0 ;
• 考慮0
bool result = a && !( a & ( a – 1 ) ) ;
13. 計算有幾個 bit 是 1
• 基礎方法
for( cnt = 0 ; a ; a >>= 1 ) cnt += a & 1 ;
• 查表
cnt = table256[ a & 0xff ] +
table256[ ( a >> 8 ) & 0xff ] +
table256[ ( a >> 16 ) & 0xff ] +
table256[ a >> 24 ];
14. 往上取2的冪次
• 例子: 5 ⇒ 8
• --a ;
a |= a >> 1 ;
a |= a >> 2 ;
a |= a >> 4 ;
a |= a >> 8 ;
a |= a >> 16 ;
++a ;
15. 最右邊的 1
• 也叫 lowbit
• 例子: 010010 2 ⇒ 000010 2
101000 2 ⇒ 001000 2
• lowbit(x) = x & ( -x ) ;
17. 集合
• 有一個由 0, 1, ⋯ , 𝑛 − 1 構成的集合 𝑆
• 我們可以用一個 𝑛 bit的整數 𝑚 𝑆 來表示 𝑆
• 第 𝑖 個 bit 為 1 代表 𝑖 在 𝑆 裡面(從右邊數)
• 例子:
𝑛 = 5
𝑆 = 0, 2, 3 ⇒ 𝑚 𝑆 = 01101 2
𝑆′
= 1, 2, 4 ⇒ 𝑚 𝑆′ = 10110 2
18. 常用的集合
• 𝑆1 = 0, 1, ⋯ , 𝑛 − 1
𝑚 𝑆1
= ( 1 << n ) – 1 ;
• 𝑆2 = 𝑖
𝑚 𝑆2
= 1 << i ;
20. 聯集 Union
• 聯集其實就是在做 bitwise OR
• 𝑚 𝑆∪𝑆′ = 𝑚 𝑆 | 𝑚 𝑆′
• 例子:
𝑛 = 5
𝑆 = 0, 3, 4 ⇒ 𝑚 𝑆 = 11001 2
𝑆′
= 0,1,4 ⇒ 𝑚 𝑆′ = 10011 2
𝑆 ∪ 𝑆′
= 0,1,3,4
⇒ 𝑚 𝑆∪𝑆′ = 11011 2
25. 枚舉子集
• 有時會需要枚舉子集合
• 例子:
𝑆 = 0, 1, 3
∅, 0 , 1 , 3 , 0,1 , 0,3 , 1,3 , 0,1,3
0000, 0001, 0010, 1000,0011, 1001, 1010, 1011
26. 枚舉子集 - simplified
• 先考慮比較簡單的版本
• 目標:枚舉 𝑆 = 0, 1, ⋯ , 𝑛 − 1 的子集合
• 作法:就是 0 ~ 2 𝑛
− 1
– 0...000
– 0...001
– 0...010
– 0...011
– ...
– 1...111
27. 枚舉子集 - original
• 目標:枚舉 𝑆 的子集合
• 有一些用不到的 bit 怎麼辦?那就不要考慮他們!
for ( int sub = sup ; ; sub = ( sub - 1 ) & sup ) {
// do something
if ( sub == 0 ) break ;
}
28. 枚舉子集 2
• 有時需要枚舉大小為 𝑘 的子集合們
• 例子:
𝑆 = 0, 1, 3 , 𝑘 = 2
0,1 , 0,3 , 1,3
0011, 1001, 1010
29. 枚舉子集 2 - simplified
• 先考慮 𝑆 = 0, 1, ⋯ , 𝑛 − 1
• 例子:
int lower = ( 1 << k ) - 1, upper = 1 << n ;
for ( int comb = lower ; comb < upper ; ) {
// do something
comb = next_permu( comb ) ;
}
30. 枚舉子集 2 - simplified
• 重點是找出下一個排列,自己畫個圖看看
int next_permu( int p ) {
int x = lowbit( p ), y = p + x ;
return y | ( ( p & ~y ) / x >> 1 ) ;
// or return y | ( ( p & ~y ) >> ( lg( x ) + 1 ) ) ;
}