位运算

n的二进制表示中第k位是几

思想

  • 先把第k位移到最后一位

    实现方式是用右移运算 n >> k

  • 再看最低位是几

    假设前一步得到x, 最低位为 x & 1

代码

# include<iostream>

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    
    int res = n >> k & 1;  // 注意 k = 0 就是第 0 位
    cout << res;
    return 0;
}

lowbit(x)

lowbit(x)是x的二进制表达式中最低位的1所对应的值, 是树状数组的一个基本操作

举个例子

\(x = (1010)_2\)\(lowbit(x) = (10)_2\)

\(x = (101000)_2\)\(lowbit(x) = (1000)_2\)

思想

\(lowbit(x) = x \& (-x)\)

拿上面的例子一来看 \(x = (0 000 1010)_2, -x = (11110110)_2\)

解释一下为什么, 在存储过程中是补码, 最高位为符号位, 在与运算时符号位也会参与运算

上面相与得到 \((00001010)_2 \& (11110110)_2 = (00000010)_2\)

又有 \((-x) = {\sim}x + 1\) ~是非运算比如 \(x = (0 000 1010)_2, {\sim}x = (11110101)_2\)

代码

# include <iostream>

using namespace std;

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

int lowbit2(int x) {
    return x & (~x + 1);
}

int main()
{
    int x;
    cin >> x;
   	cout << lowbit1(x) << endl << lowbit2(x);
}

应用

求x二进制表示中1的个数

题目

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

输入格式

第一行包含整数 n。

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

输出格式

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

数据范围

\(1≤n≤100000\)
\(0≤数列中元素的值≤10^9\)

输入样例:

5
1 2 3 4 5

输出样例:

1 1 2 1 2
代码
# include<iostream>

using namespace std;

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

int count_one(int x) {
    int  count = 0;
    while(x != 0) {
        x -= lowbit(x);
        count ++;
    }
    return count;
}

int main(){
    int n, x;
    cin >> n;
    for(int i = 0; i < n; i ++){
        cin >> x;
        cout << count_one(x) << " ";
    }
}
posted @ 2023-03-18 14:56  我就一水  阅读(32)  评论(0编辑  收藏  举报