集合的整数表示
当集合中的元素较少时,我们可以通过二进制码来表示集合,这样枚举子集什么的就更加方便快捷吗,有多快可以从下面的代码看出
空集 0
只含有第i个元素的集合{i} 1<<i
含有全部n个元素的集合 (1<<n)-1
判断第i个元素是否属于集合S if(S>>i &1)
向集合中加入第i个元素 S|(1<<i)
从集合中去除第i个元素 S&~(1<<i)
集合S和T的并集 S|T
集合S和T的交集 S&T
枚举某个集合sup=01101101的集合
暴力枚举显然太二,考虑(sub+1)&sup但是这样sub并不一定会增加
所以考虑降序的(sub-1)&sup,这样能一直减下去
int sub=sup;
do
{
sub=(sub-1)&sup
}while(sub!=sup)//处理完0后,会有sub=-1,-1&sup=sup
再来说从{0,1,2,3,4,5,6。。。。n-1}的集合中枚举大小为k的子集
最小的子集为(1<<k)-1
int comb=(1<<k)-1;
while(comb<1<<n)
{
int x=comb&-comb,y=comb+x;
comb=((comb&~y)/x)|y;
}
上面的代码意思就是,例如有0101110;
我们把连续的后面的111最高位往前进一位,其余的右移,下一个结果是0110011