ACM 利用位运算枚举所有子集

    xiaoxiao2021-03-25  124

            给集合里的元素一个顺序,那么就可以用整数表示集合,某一位为1表示对应元素被选取。

            设x为表示集合的整数,那么这个整数有如下性质:

             x的子集整数y在数值上不会比x大。因为x的子集y只是保留了x某些位置上的1,所以y总可以加上一个非负的整数z等于x,相当于把没选的1补上。

             根据这个性质可知,可以通过枚举所有比x小的数p并判断,p是否只含x对应位上的1,如果是则p是x的子集,否则不是。这样时间复杂度是严格的x。有没有更快的呢,有的。

    上诉枚举p是通过减一操作,并且我们知道减一操作一定是正确的,那么在枚举的时候如何快速的去掉多余的状态,答案就是和x进行&(与)运算。与运算可以快速跳到下一个子

    集。

             &运算本质就是保留p在x对应位为1的数值,而根据二进制减法可知减一操作都是把p最低位的1消去,在那一位后全补上1,如果在x对应位为0的地方产生了1其实是无效的,

    后续的减一操作也会把它消掉,所以直接&运算可以快速去掉多余的状态。时间复杂度是x的子集数。

             代码如下:

    for(int i=x;i;){ i=(i-1)&x; }

    转载请注明原文地址: https://ju.6miu.com/read-22825.html

    最新回复(0)