NOIP 普及组初赛 · NOIP 2018 普及组初赛试题 第 14 题

选择题 · 答案 B · 考点:进制与编码、循环结构

← 整套速查表 NOIP 普及组初赛 全部真题

题目

为了统计一个非负整数的二进制形式中 $1$ 的个数,代码如下:

int CountBit(int x)
{
	int ret = 0;
	while (x)
	{
		ret++;
		___________;
	}
	return ret;
}

则空格内要填入的语句是( )。

答案:B

考点

进制与编码循环结构

解题思维

这题考位运算里数二进制1个数的经典技巧。拿到题先想:循环里 ret++ 后必须消掉一个1,否则死循环。直接代入 x&=x-1 试一下,发现每轮正好抹掉最低位的1,循环次数就是1的个数,这就是 Brian Kernighan 算法。

常见错误

学生容易把统计1的个数和统计位数搞混,看到右移就选 A;或者没意识到 C、D 会让 x 变大导致死循环,只盯着 B 的语法像而忽略逻辑;还有人记混位运算公式,把 x&(x-1) 和 x&(-x) 搞反,导致在树状数组或判2的幂时出错。

详细解析(节选)

考点与命题视角

本题属于“进制与编码”中的位运算技巧,核心是Brian Kernighan 算法:每次用 x & (x-1) 把最低位的 1 消掉,循环次数即为 1 的个数。命题人常在这里挖坑:四个选项全是位运算,A 是右移(统计位数),C 是制造更多 1(死循环),D 是左移(死循环),只有 B 符合“消 1”的逻辑。学生若只背公式不代入验证,很容易误选。

逐空推演(以 x=5 为例)

原代码框架:

int CountBit(int x)
{
    int ret = 0;
    while (x)
    {
        ret++;
        _____________;
    }
    return ret;
}

目标:让 ret 最终等于二进制中 1 的个数。while(x) 保证循环在 x 变为 0 时终止,因此每轮必须至少消掉一个 1,否则 x 永远不为 0,程序卡死。

代入选项验证

只有 B 能让每轮减少一个 1,循环次数恰好等于 1 的个数。

同考点真题

在 OI伴学 里做这道题
登录后可计时作答、查看完整六段式解析,并按你的错题自动生成同类练习。
去刷题先做一次 AI 学情诊断