题解:AcWing 801 二进制中1的个数
【题目来源】
AcWing:801 二进制中1的个数 - AcWing题库
【题目描述】
给定一个长度为 \(n\) 的数列,请你求出数列中每个数的二进制表示中 \(1\) 的个数。
【输入】
第一行包含整数 \(n\)。
第二行包含 \(n\) 个整数,表示整个数列。
【输出】
共一行,包含 \(n\) 个整数,其中的第 \(i\) 个数表示数列中的第 \(i\) 个数的二进制表示中 \(1\) 的个数。
【输入样例】
5
1 2 3 4 5
【输出样例】
1 1 2 1 2
【核心思想】
-
问题分析:给定 \(n\) 个整数,求每个整数的二进制表示中 \(1\) 的个数。这是一个位运算问题,关键在于高效地统计二进制中 \(1\) 的数量。
-
算法选择:
- lowbit 技巧:利用
x & -x获取 \(x\) 的二进制表示中最低位的 \(1\) 所对应的值 - 迭代消去:不断减去最低位的 \(1\),直到 \(x\) 变为 \(0\),统计减法次数即为 \(1\) 的个数
- lowbit 技巧:利用
-
关键步骤:
- 定义 lowbit 函数:
lowbit(x) = x & -x- 原理:
-x是 \(x\) 的补码(按位取反后加 \(1\)),x & -x可以提取出最低位的 \(1\) - 例如:
x = 10100(二进制),-x = 01100(补码),x & -x = 00100 = 4
- 原理:
- 统计每个数字(对于每个输入的 \(x\)):
- 初始化
res = 0 - 循环(当 \(x \neq 0\)):
x -= lowbit(x):减去最低位的 \(1\)res++:计数器加 \(1\)
- 输出
res
- 初始化
- 定义 lowbit 函数:
-
时间/空间复杂度:
- 时间复杂度:\(O(n \cdot \log x)\),对于每个数字,最多进行 \(\log x\) 次循环(\(x\) 的二进制位数)
- 空间复杂度:\(O(1)\),仅使用常数额外空间
-
lowbit 的核心思想:
- 补码性质:
-x = ~x + 1,即 \(x\) 的按位取反加 \(1\) - 提取最低位 1:
x & -x的结果只保留 \(x\) 中最低位的 \(1\),其余位都为 \(0\) - 快速消去:每次减去
lowbit(x)可以消去一个 \(1\),比逐位检查更高效 - 适用场景:
- 统计二进制中 \(1\) 的个数
- 树状数组(Binary Indexed Tree)中的索引计算
- 快速获取最低位的 \(1\) 的位置
- 补码性质:
【解题思路】

【算法标签】
位运算
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int lowbit(int x) // 返回x的二进制表示中最低位的1所对应的值
{
return x & -x;
}
int main()
{
int n;
cin >> n; // 输入数字个数
while (n--) // 处理每个数字
{
int x;
cin >> x;
int res = 0; // 统计1的个数
while (x) // 当x不为0
{
x -= lowbit(x); // 减去最低位的1
res++; // 计数器+1
}
cout << res << " "; // 输出结果
}
return 0;
}
【运行结果】
5
1 2 3 4 5
1 1 2 1 2
浙公网安备 33010602011771号