1. 程式人生 > >ACM 利用位運算列舉所有子集

ACM 利用位運算列舉所有子集

        給集合裡的元素一個順序,那麼就可以用整數表示集合,某一位為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;
}