今天发现了一个使用位运算枚举二进制子集的风骚方法,特记录一下:
枚举子集
设 \(s\) 为要被枚举的集合:
1 | for(int i=s;i;i=(i-1)&s) |
当 \(s=7=(111)_2\) 时,上述代码的运行结果为:
1 | 0111 |
枚举出的结果是递减的。
枚举固定大小的子集
设 \(n\) 为集合大小,\(m\) 为要枚举的子集大小:
1 | for(int i=(1<<m)-1,x,y;i<(1<<n);x=i&-i,y=i+x,i=((i&~y)/x>>1)|y) |
当 \(n=4,m=2\) 时,上述代码的运行结果为:
1 | 0011 |
枚举出的结果是递增的。
评语
太 TM 骚了……