二进制中1的个数

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

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

输入格式

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

输出格式

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

数据范围

1n100000{\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=00001010\rm{x}=\rm{000}\cdots\rm{01010} 为例:
源码(xx):00001010\rm{000}\cdots\rm{01010}
反码(x\sim x):11110101\rm{111}\cdots\rm{10101}
补码(x+1\sim x+\rm{1}):11110110\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;
}

评论区