二进制枚举利用的是二进制下n位长度的数有2 ^ n个,一个有n个元素的集合子集个数也为2 ^ n个,所以可以利用二进制的1,0和集合中的元素联系起来他可以实现组合也可以实现容斥
对一个二进制来说1代表取这个元素0代表不取这个元素,1和0所在的位置代表元素的位置
举个例子
如集合{a,b,c,d,e}
当二进制00000就代表什么都不取, 10000代表取a,01000代表取b,11000代 表取a,b,如此,所以我们需要枚举的数量就是00000到11111,也就是0到1<<n位,<<代表左移操作,即乘2。
题目:
从 1∼n这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式
输入一个整数 n。
输出格式
每行输出一种方案。
同一行内的数必须升序排列,相邻两个数用恰好 1 个空格隔开。
对于没有选任何数的方案,输出空行。
本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
数据范围
1≤n≤15
输入样例:
3
输出样例:
1. 2. 3 3. 2 4. 2 3 5. 1 6. 1 3 7. 1 2 8. 1 2 3
//AC代码 #include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; for(int i=0;i<1<<n;i++) { for(int j=0;j<n;j++) { if(i>>j&1) cout<<j+1<<" "; } cout<<endl; } return 0; }
开始第一个循环的(1<<n)实际上是枚举出n个数每一个的取和不取的情况,每一个数取和不取用1位二进制表示,0表示不取.表示取,然后n个数取和不取的情况就需要长度为n的一个01串表示。他们取和不取的情况,第二个for循环是根据第一个循环枚举的01串的长度来对这次枚举的01串各个位上是否为1(也就是是否取这个数)进行判断1<<就是得到某一个01串上只有个位置为1的一个数这个数和你第一次循环枚举的进行&操作(根据&操作相同01串的位上同为1得到的才为1如果枚举的这个01串上该位不为1那么(1<<得0为0也就是不取的情况不进
入语句)然后这个第二个for循环就可以判断出枚举到这个01串哪些位置上为1(就是取哪些数)