You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
二进制数的子集数量计算
|
|
|
|
|
子集指的是在原二进制数中1的选择,假设对应的二进制数中有数字1共n个,那么最少选择1个,最多选择n-1个,请找出所有的这样的二进制数子集。
|
|
|
|
|
比如二进制数13=(1101)b,有3个位置存在数字1,
|
|
|
|
|
那么:
|
|
|
|
|
包含1个1的:1000,0100,0001
|
|
|
|
|
包含2个1的:1100,1001,0101
|
|
|
|
|
共6个
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// 输出十进制对应的二进制数(模板)
|
|
|
|
|
void print(int n) {
|
|
|
|
|
printf("%2d:", n);
|
|
|
|
|
// 输出4个数位的二进制数
|
|
|
|
|
for (int i = 3; i >= 0; i--) // 由高到低位
|
|
|
|
|
printf("%d", n >> i & 1);
|
|
|
|
|
puts("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
输出n的所有二进制子集
|
|
|
|
|
方法1:逻辑清晰,但性能差
|
|
|
|
|
|
|
|
|
|
理解一下:
|
|
|
|
|
(1) i=n-1:显然,子集不包含自身,也就是最大是比自己小1的才可能是第一个最大子集
|
|
|
|
|
(2) for (int i = n - 1; i; i--),从可能的最大子集开始,一个个减少,当然可以遍历到每个可能的子集
|
|
|
|
|
(3) if ((i & n) == i) 这个位运算,就是通过数位上数字1的与运算,只有超集与之相与,才能保证得到自身,挺好理解
|
|
|
|
|
*/
|
|
|
|
|
void sub1(int n) {
|
|
|
|
|
for (int i = n - 1; i; i--)
|
|
|
|
|
if ((i & n) == i) print(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
方法2:优化
|
|
|
|
|
*/
|
|
|
|
|
void sub2(int n) {
|
|
|
|
|
for (int i = n - 1; i; i = (i - 1) & n)
|
|
|
|
|
print(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
int st = 13; // 1101
|
|
|
|
|
sub1(st);
|
|
|
|
|
printf("==================================\n");
|
|
|
|
|
sub2(st);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|