枚举大小为k的子集

Posted autoint

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了枚举大小为k的子集相关的知识,希望对你有一定的参考价值。

这种位操作不大可能分析出来,先看代码再分析。

代码

使用条件:(k>0)

void solve(int n,int k)
{
    for(int comb = (1 << k) - 1; comb < (1 << n);)
    {
        // ...
        int x = comb & -comb, y = comb + x;
        comb = (((comb & ~y) / x ) >> 1) | y;
    }
}

证明

[ egin{array}{} 首先是辅助变量x,yx ightarrow comb最低位y ightarrow comb的倒数第一段1取0,该1段前一个位置的0取1设上述y改变的部分为lencomb&sim y ightarrow len前取0,len中取1,len后取0(comb&sim y)/x ightarrow 长度为len的全1串((comb & sim y) / x ) >> 1 ightarrow 右移1位,len-1综上(((comb & sim y) / x ) >> 1) | y ightarrow 把comb的len的前一个位置的0取1,末尾添上len-1个1 end{array} ]

然后这就是不重不漏的枚举。
所以时间复杂度(Oleft(inom{n}{k} ight))


以上是关于枚举大小为k的子集的主要内容,如果未能解决你的问题,请参考以下文章

计算给出数组中最小标准差的子集

大小为 K 的子集的乘积之和

总和小于 M 的大小为 K 的子集的最大总和

HDU 5616 Jam's balance(暴力枚举子集)

(二进制枚举子集)买玩具

具有固定子集大小的 Sum-subset