acwing 801. 二进制中1的个数(位运算)

这里主要讲解两个公式:

  1. n >> k & 1 : 看第k位是几
  2. lowbit(x){return x&(-x);} : 返回n的最后一位1

n的二进制表示中第k位是几
acwing 801. 二进制中1的个数(位运算)_第1张图片
步骤:
3. 先把第k位移动最后一位 n >> k
4. 看个位是几 x & 1

综合 : n >> k & 1

举例:
输出一个数的二进制数, 10 = 1010

#include 

using namespace std;

int main()
{
    int n = 10;
    for(int k = 3; k >=0; k --) cout << (n >> k & 1);
    return 0;
}

第二个公式: lowbit(x) : 返回x 的最后一位 1
例如 x = 1010 lowbit(x) = 10 (这里是二进制数)
x = 101000 lowbit(x) = 1000 (返回最后一个1,二进制数)

原理: lowbit(x) = x & (-x) = x & (~x + 1)
一个负数 在计算机中又等于它的取反 + 1: -x = ~x + 1
acwing 801. 二进制中1的个数(位运算)_第2张图片

题目:
给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。

输入格式
第一行包含整数 n。

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

输出格式
共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表示中 1 的个数。

数据范围
1≤n≤100000,
0≤数列中元素的值≤109
输入样例:
5
1 2 3 4 5
输出样例:
1 1 2 1 2

code:

#include 

using namespace std;

int lowbit(int x)
{
    return x & -x;
}

int main()
{
    int n;
    cin >> n;
    
    while(n -- )
    {
        int x ;
        cin >> x;
        
        int re = 0;
        while(x) x -= lowbit(x), re ++;   // 每次减去x的最后一位1
        cout << re << ' ';
    }
    cout << endl;
    return 0;
}

复习概念:
原码、反码、补码
正数三码合一, 负数补码就是反码加 1
acwing 801. 二进制中1的个数(位运算)_第3张图片
查询负数在计算机中的表示

int main()
{
    int n =10;
    unsigned int x = -n;
    for(int i =31; i >=0; i --) cout << (x >> i & 1);
    
    return 0;
}

那为什么计算机中的负数用补码表示呢(为什么不用反码表示)

  1. 因为计算机中是没有减法的
  2. 性质上, 一个数加上相反数等于0

0 - x : 其实是32 个0 - x, 不够减, 需要在前面加上1, 其实这里就等于~x + 1
acwing 801. 二进制中1的个数(位运算)_第4张图片

你可能感兴趣的:(#,算法刷题(基础模板应用),算法,c++,贪心算法)