二進制枚舉有啥用?
代碼短,比起dfs枚舉還要快
怎么枚舉的?
比如你有三個物品,你只需要從0枚舉到2^3-1=7就可以了(dfs枚舉我就不說了)
為什么呢?
0——7這幾個數的二進制形式如下
0——000
1——001
2——010
3——011
4——100
5——101
6——110
7——111
你可以把1當作選這個物品,0代表不選這個物品。每一個位置上對應一個物品的選擇
什么意思呢?
就比如2——010
我們就可以定義從左到右第一個位置對應1號物品的選與不選,從左到右第二個位置對應2號物品的選與不選,從左到右第三個位置對應3號物品的選與不選
那么2——010代表的意義就是第一個物品不選,第二個物品要選,第三個物品不選
而且從0——7的每一個數都具有這樣的意義。那么可以說從0——(2^n)-1(n代表n個物品)這樣枚舉,這號可以把所有狀態枚舉到
一些位運算符
按位與運算符(&)
參加運算的兩個數據,按二進制位進行“與”運算。
運算規則:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:兩位同時為“1”,結果才為“1”,否則為0
例如:3&5 即 0000 0011& 0000 0101 = 00000001 因此,3&5的值得1。
左移運算(<<)
a << b就表示把a轉為二進制后左移b位(在后面添b個0)。例如100的二進制為1100100,而110010000轉成十進制是400,那么100 << 2 = 400。可以看出,a << b的值實際上就是a乘以2的b次方,因為在二進制數后添一個0就相當於該數乘以2(這樣做要求保證高位的1不被移出)。
通常認為a << 1比a * 2更快,因為前者是更底層一些的操作。因此程序中乘以2的操作請盡量用左移一位來代替。
除了左移還有右移,右移代表除2(只保留整數部分)
a<<b 代表:a的二進制形式向左移動了b個位置,相當於乘了b個2
a>>b 代表:a的二進制形式向右移動了b個位置,相當於除了b個2
代碼:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int main() 6 7 { 8 9 int n; 10 11 cin >> n; 12 13 for(int i = 0; i < (1<<n); i++) //從0~2^n-1個狀態 14 15 { 16 17 for(int j = 0; j < n; j++) //遍歷二進制的每一位 18 19 { 20 21 if(i & (1 << j))//判斷二進制第j位是否存在 22 23 { 24 25 printf("%d ",j);//如果存在輸出第j個元素 26 27 } 28 29 } 30 31 printf("\n"); 32 33 } 34 35 return 0; 36 37 }