给定一个长度为 $n$ 的序列,请你求出数列中每个数的二进制表示中 $\rm{1}$ 的个数。
输入格式
第一行包含整数 $n$。
第二行包含 $n$ 个整数,表示整个数列。
输出格式
共一行,包含 $n$ 个整数,其中的第 $i$ 个数表示数列中的第 $i$ 个数的二进制表示中 $\rm{1}$ 的个数。
数据范围
${\rm{1}} \le {\rm{n}} \le {\rm{100000}}$
${\rm{0}} \le {\rm{数列中元素的值}} \le {\rm{10^9}}$
输入样例
5
1 2 3 4 5
输出样例
1 1 2 1 2
题解
(lowbit)
$(\rm{x}\&\rm{-x})\Longleftrightarrow(\rm{x}\&(\sim\rm{x+1}))$
例如二进制 $\rm{1010101000}$ 经过 $\sim$ 运算后为 $\rm{0101010111}$,$+1$ 后为$\rm{0101011000}$,故 $\rm{x}\&(\sim\rm{x+1}))$ 将最后一个 $\rm{1}$ 之前的所有数都与为 $\rm{0}$,即 $\begin{bmatrix} 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 & 1 & 1 & 0 & 0 & 0\end{bmatrix}$ 或运算后得到 $\rm{0000001000}$。
基础拓展:
以 $\rm{x}=\rm{000}\cdots\rm{01010}$ 为例:
源码($x$):$\rm{000}\cdots\rm{01010}$
反码($\sim x$):$\rm{111}\cdots\rm{10101}$
补码($\sim x+\rm{1}$):$\rm{111}\cdots\rm{10110}$
计算机中使用补码来存储负数。
C++ 代码
#include <iostream>
using namespace std;
int lowbit(int x)
{
return x & -x;//x & (~x + 1)
}
int main()
{
int n;
cin >> n;
while(n--)
{
int x, res = 0;
cin >> x;
while(x)
x -= lowbit(x), res++; //每次减去x的最后一位1
cout << res << " ";
}
return 0;
}
版权属于:字节星球/肥柴之家 (转载请联系作者授权)
原文链接:https://www.bytecho.net/archives/1782.html
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。