题意简述
小C最近在学习二进制运算,他发现每个非负整数都有其独特的二进制表示。比如,整数 5 可以用二进制表示为 "101",而整数 11 则表现为 "1011"。值得注意的是,除了 N = 0 的情况外,任何非负整数的二进制表示都不应该有前导零,这一点非常重要。
在这个过程中,小C还接触到了反码的概念。二进制的反码表示是指将每一个 1 变为 0,每一个 0 变为 1。例如,数值 5 的二进制表示为 "101",那么它的反码就是 "010"。小C对这个概念产生了浓厚的兴趣,他想要计算一个给定十进制数 N 的二进制反码所对应的十进制数。
思路分析
这道题的核心在于计算某个非负整数 N 的二进制反码对应的十进制值。我们可以通过几个简单的步骤来完成这个计算。观察输入与输出之间的关系,我们发现它们的和加上 1 恰好是某个 2 的次方数。具体来说,假设 N 的二进制表示为 ,其中 k 表示最高位的索引。计算反码的过程可以分为以下几步:
- 确定位数:首先,我们需要确定
N的二进制表示所占的位数。可以使用N.bit_length()来获取这个位数,这对于后续的计算至关重要。 - 计算补码:利用位数,我们可以计算出
2^m的值,其中m是N的位数。补码的计算公式为2^m - 1 - N。这里,2^m - 1表示的是m位全为1的二进制数。 - 得到反码:反码则是补码减去
1,所以我们可以得到反码的公式为2^m - 1 - N - 1,简化后即为2^m - 2 - N。 - 特殊情况处理:需要特别注意的是,当
N = 0时,反码对应的十进制值为1。这是因为在二进制中,0被视为占用一位。
举个例子
为了更好地理解这一过程,我们可以通过一个具体的例子来说明,假设我们要计算 N = 5 的反码对应的十进制数。
-
确定位数:首先,将
5转换为二进制,得到"101"。我们可以看到,这个二进制数占用3位,因此m = 3。 -
计算补码:
- 首先计算
2^m的值:2^3 = 8。 - 然后,计算补码:
8 - 5。这里8 - 5得到的是3,即二位二进制数11,所以补码为3。
- 首先计算
-
得到反码:
- 反码的计算公式是补码减去
1:3 - 1 = 2。
- 反码的计算公式是补码减去
-
确认结果:因此,
N = 5的反码对应的十进制数为2。我们可以验证,5的二进制反码是"010",在十进制中对应的值是2,所以最终答案是3 - 1 = 2。
代码
int solution(int N) {
if (!N) {
return 1;
}
int NN = N, n = 0;
while (N) {
n++;
N >>= 1;
}
long long tmp = 1LL << n;
return tmp - NN - 1;
}