ACM位运算&bitset总结

来源:互联网 发布:淘宝店铺怎么上众划算 编辑:程序博客网 时间:2024/04/29 12:14

转载至http://blog.csdn.net/mtrix/article/details/61200302 

给集合里的元素一个顺序,那么就可以用整数表示集合,某一位为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;  }  


①判断n是否是2的整次幂 link

bool fun(int n){    return (!(n & (n-1))) && n;}



lowbit(x)是x的二进制表达式中最低位的1所对应的值。
比如,6的二进制是110,所以lowbit(6)=2。

int lowbit(int x){  return x&(-x);  }  
去除某个数的某一位

bool get_bit(int t,int x) {    //    在 t 中,取出第 x 位     --从零开始    return t & (1<<(x));}
改位

#define set_bit(x,ith,bool) ((bool)?((x)|(1<<(ith))):((x)&(~(1<<(ith)))));//从零开始//  设置 x 的从第 ith 位起连续 k 位 为bolint mset(int x,int ith,int k,int bol){        while(k --)x = set_bit(x,ith+k,bol);        return x;}


gcc编译器的内建函数,__builtin_popcount(x)

直接统计整数x转换成2进制中有多少1。


bitset

什么是bitset

bitset 是STL库中的二进制容器,根据C++ reference 的说法,bitset可以看作bool数组,但优化了空间复杂度和时间复杂度,并且可以像整形一样按位与或。

使用方法

申明

bitset的申明要指明长度

1
bitset<length> bi

这样就申明了一个长度为length的名叫bi的bitset

 赋值

bitset重载了[]运算符,故可以像bool数组那样赋值

bi[2] = 1;

这样就能将第二位赋值为1

常用函数

b1 = b2 & b3;//按位与b1 = b2 | b3;//按位或b1 = b2 ^ b3;//按位异或b1 = ~b2;//按位补b1 = b2 << 3;//移位
int one = b1.count();//统计1的个数

优化作用

常常碰到处理的数组只有0和1的变化,此时就可以使用bitset优化。比如求两个集合的交集可以使用按位与运算,求并集可以使用按位或运算


常用的成员函数:
b.any() b中是否存在置为1的二进制位?
b.none() b中不存在置为1的二进制位吗?
b.count() b中置为1的二进制位的个数
b.size() b中二进制位数的个数
b[pos] 访问b中在pos处二进制位
b.test(pos) b中在pos处的二进制位置为1么?
b.set() 把b中所有二进制位都置为1
b.set(pos) 把b中在pos处的二进制位置为1
b.reset( ) 把b中所有二进制位都置为0
b.reset( pos ) 把b中在pos处的二进制位置置为0
b.flip( ) 把b中所有二进制位逐位取反
b.flip( pos ) 把b中在pos处的二进制位取反
b.to_ulong( ) 把b中同样的二进制位返回一个unsigned




0 0