位运算
\(\text{lowbit}\) 运算
介绍
对于一个数 \(x\) ,每次读取 \(x\) 二进制表示下的最后面的 \(1\) 所表示的数 ,即 \(lowbit(x)\) 。
例如:
\(lowbit(7)\) = \(1\).
\(lowbit(4)\) = \(4\).
\(lowbit(6)\) = \(2\).
通过 \(lowbit\) 运算,可以获得一个数二进制下所有是 \(1\) 的位数。
读取最后一位 \(1\) 的方法:
1.令 \(y\) \(=\) \(\sim\) \(x\) \(+\) \(1\)。
设最后一位 \(1\) 在第 \(i\) 位。则取反后,\(0\) \(\sim\) \(i - 1\) 位为 \(1\) ,第 \(i\) 位为 \(0\)。
再加 \(1\) 就可通过进位,令 \(0\) \(\sim\) \(i - 1\) 位为 \(0\) , 第 \(i\) 位为 \(1\) 。
2.令 \(num\) \(=\) \(y\) & \(x\)。
将两个数相与,就能得到只有第 \(i\) 位为 \(1\) ,其他位都为 \(0\) 的数 \(num\) 。
用 \(x\) 减去 \(num\) ,就能减去最后一位 \(1\) 。
在补码表示下: \(\sim\)n \(=\) \(-\) \(1\) \(-\) \(n\) 。
\(\sim\) \(n\) \(+\) \(1\) \(=\) \(-\) \(n\) 。
用处
提取二进制 \(x\) 中所有是 \(1\) 的位数。
\(\text{code}\)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main(){
int x;
scanf("%d",&x);
while(x!=0){
int num=x&-x;
x-=num;
cout<<num<<" ";//最后一位 1 与后面的0共同所代表的数
cout<<(log(num)/log(2))<<endl;//这个数是二的多少次方
}
return 0;
}
输入
5
输出
1 0
4 2
题目
\(1.\) P7071 优秀的拆分
\(2.\) P7076 [CSP-S2020] 动物园