子集生成 -- 二进制法

#include<iostream>
using namespace std;


void print_subset(int n, int s)        //打印{0,1....n-1}的子集S
{
    static int count = 1;
    cout << "第"<<count++<<"个子集是: ";
    for(int i = 0; i < n; i++)    
    {
        if(s&(1<<i))
            cout << i <<' ';
    }
    cout << endl;
}

int main()
{
    int n;
    cout << "请输入一个整数: ";
    cin >> n;
    cout << n << "的自己如下: \n";
    for(int i = 0; i < (1<<n); i++)
    {
        print_subset(n,i);
    }    

}




子集的定义是基于一个长度为 $N$ 的二制字符串 $st$,其所有的子集构成了一个集合 $\text{Subs}(st)$。这个集合包含所有可以通过将 $st$ 中某些位从 `1` 变为 `0` 而得到的二制字符串组合。例如,当 $st = 101$ 时,$\text{Subs}(st) = \{101, 100, 001, 000\}$ [^1]。 ### 二子集的相关算法 #### 1. 子集前缀和 给定一个整数 $N$(表示二制字符串的长度)以及一个数组 $\text{Val}[st]$,其中 $st$ 是长度为 $N$ 的二制字符串,可以计算每个二制字符串 $st$ 的子集前缀和 $\text{Sum}[st]$。这个值是所有 $st$ 的子集对应的 $\text{Val}$ 值之和。例如,$\text{Sum}[101] = \text{Val}[101] + \text{Val}[100] + \text{Val}[001] + \text{Val}[000]$ [^1]。 #### 2. 枚举全组合子集 为了枚举一个二制字符串的所有子集,可以使用二制计数的方法。例如,通过循环遍历从 $0$ 到 $2^N - 1$ 的所有整数,每一个整数都可以被看作是一个二制字符串,从而生成对应的选择组合。例如,在 C++ 中,可以使用如下代码: ```cpp vector<vector<int>> subsets(vector<int>& nums) { int n = nums.size(); vector<vector<int>> vv; // 二制枚举所有情况 for (int i = 0; i < (1 << n); i++) { vector<int> tmp; // 对每一位的选择行展开 for (int j = 0; j < n; j++) { // 二制值对应位置为1就插入子集 if (i >> j & 1) tmp.push_back(nums[j]); } vv.push_back(tmp); } return vv; } ``` 这段代码展示了如何通过二制枚举来生成所有可能的子集 [^4]。 #### 3. 容斥原理与子集 在已知每个二制字符串 $st$ 的子集和 $\text{Sum}[st]$ 的情况下,如果需要求解某个特定的原始值 $\text{Raw}[x]$,可以应用容斥原理来推导出该值。这种方法通常涉及到对子集和的逆向操作,以提取单个元素的价值 [^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值