位运算的常用技巧
功能 | 示例 | 式子 |
---|---|---|
去掉最后一位 | 10110->1011 | x>>1 |
在最后添加0 | 1011->10110 | x<<1 |
在最后添加1 | 1011->10111 | (x<<1)|1 |
右数第k位成为1 | 100011->101011,k=4 | x|(1<<(k-1)) |
右数第k位成为0 | 101011->100011,k=4 | x&~(1<<(k-1)) |
获取右数第k位 | 101011->1,k=4 | (x>>(k-1))&1 |
截取最后的k位 | 101011->1011,k=4 | x&((1<<k)-1) |
把右边连续的1变成0 | 101011->101000 | x&(x+1) |
把右起第一个0变成1 | 101011->101111 | x|(x+1) |
把右起连续的0变成1 | 101000->101111 | x|(x-1) |
把右起的第一个1变成0 | 101000->100000 | x&(x-1) |
取右边连续的1 | 101111->1111 | (x^(x+1))>>1 |
位运算的应用:
-
两数符号相同:
//判断两个数的符号相同 int x,y; bool f = ((x^y)<0);
-
判断一个数是不是2的幂次:
//判断一个数是不是2的幂次 int x; bool f=(x&(x-1))==0;
-
计算一个数的二进制有几个一:
//计算一个数的二进制有几个一 int x,c=0; for(;x;c++){ x=x&(x-1); }
-
得到右数第一个1和后面的0构成的数:
int x; //得到右数第一个1和后面的0构成的数 int lowbit(x){return x-x&(x-1)}; int lowbit(x){return x&(-x)}
集合枚举:
- 用于状态压缩是的集合枚举:
- 例如n=5,x=(11001)_2.
- 所有子集(原来为0的不变,1的位置可变可不变):
- 所有超集(原来1的位置不变,0的位置可变可不变):