$\Huge\color{orchid}{点击此处获取更多干货}$
位运算
解决这个问题只需要知道一件事,那就是数据在计算机内部全都是用二进制的方式存放的,为了便于对数据的二进制位进行操作,C++为其提供了一些按位操作的运算符
首先是移位运算符 $<<$(左移)和 $>>$(右移)
左移全部一致,丢掉高位,低位补0;右移对有符号数和无符号数不相同,无符号直接补0,有符号需要保持符号位不变,低位还是一样要丢弃(计算机组成原理考研热点)。上图易知,负数由于符号位是1,左移时符号位会被直接丢弃,所以尽量不要对负数进行左移。如果能确定是无符号数,或者能保证一定非负,那才可以放心左移(比如数组下标的类型size_t)
然后是按位逻辑运算符&(与)、|(或)、^(异或)、~(取反)
这四个运算符都是对数值二进制位的每一位对应的进行操作
统计数值二进制位的1,就可以利用移位运算和按位与运算。非负数右移,符号位永远是0,剩余数位永远补0,所以在一定次数的右移运算之后,一定能够得到0,因此可以依次将每一位移到最低位处,和1做按位与,如果非0,则说明当前最低位是1,在这个数变为0之前,按位与1结果非0的次数,就是该数二进制位1的数量
C++ 代码
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
while(n--) {
int cnt = 0, val;
cin >> val;
while(val > 0) {
if(val & 1) {
cnt++;
}
val >>= 1;
}
cout << cnt << " ";
}
cout << endl;
return 0;
}