最近刷状压dp的题目,顺便把一些位运算操作总结一下,欢迎各位dalao指正补充。
基础位运算符
右移>>:x>>1,去掉x最后一位,相当于x除以2(向下取整),比如110(6)>>1=011(3),111(7)>>1=011(3)。x>>n,去掉x后n位,相当于x除以2 n(向下取整),比如1100(12)>>2=11(3).
左移<<:x<<1,最后一位补0,相当于x乘以2,比如110(6)<<1=1100(12)。x<<n,最后补n个0,相当于x乘以2 n,比如11(3)<<2=1100(12).
与运算&:按位进行"与"操作,两数同为1结果为1,否则结果为0。例如101&110=100.
或运算|:按位进行"或"操作,两数同为0结果为0,否则结果为1。例如100|110=110.
非运算~:按位取反。例如~101=010。tip:-1二进制补码表示为11111111,其按位取反后是0.
异或运算^:按位进行"异或"操作,两数不同结果为1,否则结果为0。例如101^110=011。tip:不管是0还是1,^0都是不变的,^1都相当于取反。所以奇数^1,相当于是其-1的偶数,偶数^1,相当于是其+1的奇数.
位运算操作
假设当前状态为x.
- x<<1+1 在最后补1,也可以写成x<<1|1.
- x|1 将最后一位变成1.
- (x|1)-1 将最后一位变成0,也可以写成x&0xFFFFFFFE.
- x^1 将最后一位取反.
- x|(1<<(k-1)) 将右数第k位变成1.
- x&(~(1<<(k-1))) 将右数第k位变成0.
- (x&(1<<(k-1)))==0 判断右数第k位是否为0.
- x^(1<<(k-1)) 将右数第k位取反.
- x&((1<<k)-1) 取末k位.
- (x>>(k-1))&1 取右数第k位.
- x|((1<<k)-1) 把末k位变为1.
- x^((1<<k)-1) 末k位取反.
- x&(x+1) 将末尾连续的1变为0.
- x|(x+1) 将右数第一个0变为1.
- x|(x-1) 将末尾连续的0变为1.
- (x^(x+1))>>1 取末尾连续的1.
- x&(-x) 去掉右起第一个1的左边.
代码版,欢迎保存。
//在最后补1.
x=x<<1+1;
x=x<<1|1;
//将最后一位变成1.
x=x|1;
//将最后一位变成0.
x=(x|1)-1;
x=x&0xFFFFFFFE;
//将最后一位取反.
x=x^1;
//将右数第k位变成1.
x=x|(1<<(k-1));
//将右数第k位变成0.
x=x&(~(1<<(k-1)));
//判断右数第k位是否为0.
if((x&(1<<(k-1)))==0)
puts("Yes");
else
puts("No");
//将右数第k位取反.
x=x^(1<<(k-1));
//取末k位.
x=x&((1<<k)-1);
//取右数第k位.
x=(x>>(k-1))&1;
//把末k位变为1.
x=x|((1<<k)-1);
//末k位取反.
x=x^((1<<k)-1);
//将末尾连续的1变为0.
x=x&(x+1);
//将右数第一个0变为1.
x=x|(x+1);
//将末尾连续的0变为1.
x=x|(x-1);
//取末尾连续的1.
x=(x^(x+1))>>1;
//去掉右起第一个1的左边.
x=x&(-x);