首先二进制来表示元素的子集非常的方便,那个元素有没有了,用0 或者 1来表示;
这里需要记住两点:对于一个集合有n 个元素的集合来讲:
我们用(1 << n) - 1来表示元素的全部存在的情况,比如说:有四个元素,全部都有的情况是1111,这样也就是15,也就是1右移4位,10000,这样是16,然后-1,是15;含有一个元素的情况是(如果下标是从1开始的) 1 << (i - 1)位置,0表示空集,如果是十进制,那就是从0到15包含所有的i情况,二进制这个桥梁,让我们把每一个整数和每一种情况联系了起来:
[NOIP2002 普及组] 选数 - 洛谷
具体代码如下:
#include
#include
#include
#include
using namespace std;
//模拟递推、枚举、贪心、递归(搜索)
#define F(i,n) for(int i=0;i> n >> k;
F(i,n){
l >> number[i];
}
int u = 1 << n;
int sum = 0,ans = 0;
for(int i = 1;i < u;i ++){
sum = 0;
if(__builtin_popcount(i) == k){
for(int j = 0;j < n;j ++)
if(i & (1 << j)) sum += number[j];
if(check(sum)) ans ++;
}
}
z << ans << endl;
return 0;
}
题目二:组合的输出 - 洛谷
这个的关键就是 如何按照字典序输出,也就是10110 要比10101先出现才行,如何保证这一点呢,我们枚举符合条件的时候,倒着枚举,然后倒着输出
#include
#include
#include
#include
#include
using namespace std;
//模拟递推、枚举、贪心、递归(搜索)
#define f(i,n) for(int i=0;i> n >> r;
f(i,n){
a[i] = i + 1;
}
int u = (1 << n);
for(int i = u - 1;i >= 0;i --){
if(__builtin_popcount(i) == r){
for(int j = n - 1;j >= 0;j --){
if(i & (1 << j)){
cout << setw(3) << n - a[j] + 1 ;
}
}
cout << endl;
}
}
return 0;
}