二进制中1的个数

2021/6/4 21:25:00admin2376 阅读0 点赞0 评论

给定一个长度为 nn 的序列,请你求出数列中每个数的二进制表示中 1\rm{1} 的个数。

输入格式

第一行包含整数 nn。
第二行包含 nn 个整数,表示整个数列。

输出格式

共一行,包含 nn 个整数,其中的第 ii 个数表示数列中的第 ii 个数的二进制表示中 1\rm{1} 的个数。

数据范围

1≤n≤100000{\rm{1}} \le {\rm{n}} \le {\rm{100000}}
0≤数列中元素的值≤109{\rm{0}} \le {\rm{数列中元素的值}} \le {\rm{10^9}}

输入样例

TEXT
5
1 2 3 4 5

输出样例

TEXT
1 1 2 1 2

题解

(lowbit)

(x&−x)⟺(x&(∼x+1))(\rm{x}\&\rm{-x})\Longleftrightarrow(\rm{x}\&(\sim\rm{x+1}))
例如二进制 1010101000\rm{1010101000} 经过 ∼\sim 运算后为 0101010111\rm{0101010111},+1+1 后为0101011000\rm{0101011000},故 x&(∼x+1))\rm{x}\&(\sim\rm{x+1})) 将最后一个 1\rm{1} 之前的所有数都与为 0\rm{0},即 [10101010000101011000]\begin{bmatrix} 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 & 1 & 1 & 0 & 0 & 0\end{bmatrix} 或运算后得到 0000001000\rm{0000001000}。

基础拓展:

以 x=000⋯01010\rm{x}=\rm{000}\cdots\rm{01010} 为例:
源码(xx):000⋯01010\rm{000}\cdots\rm{01010}
反码(∼x\sim x):111⋯10101\rm{111}\cdots\rm{10101}
补码(∼x+1\sim x+\rm{1}):111⋯10110\rm{111}\cdots\rm{10110}

计算机中使用补码来存储负数。

C++ 代码

CPP
#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;
}

评论区