解方程
给定一个非负整数 $a$,请你计算方程 $a−(a \oplus x)−x=0$ 的非负整数解的数量。
其中 $\oplus$ 指按位异或。
输入格式
第一行包含整数 $T$,表示共有 $T$ 组测试数据。
每组数据占一行,包含一个非负整数 $a$。
输出格式
每组数据输出一行结果,一个整数,表示方程的非负整数解的数量。
可以证明方程的非负整数解数量总是有限的。
数据范围
前 $3$ 个测试点满足 $1 \leq T \leq 3$。
所有测试点满足 $1 \leq T \leq 1000$,$0 \leq a \leq {2}^{30}−1$。
输入样例:
3 0 2 1073741823
输出样例:
1 2 1073741824
解题思路
这题可以根据样例来找出规律,假设$a$在二进制下有$t$位$1$,那么答案就是$2^t$。
比如样例中的$1073741823 = {(111111111111111111111111111111)}_2$,有$30$个$1$,那么答案就是$2^{30} = 1073741824$。
把题目中的等式变换一下,有$a - x = a \oplus x$。考虑$a$的二进制所有位都是$1$的情况,那么对于$x$的任意一位无论是$0$还是$1$,做减法时都不会向前借位,因此任意两个位都是相互独立的。再来看一下,如果$x$的某一位为$0$,那么与$a$相应的位做减法后该位为$1$,异或运算得到的也是$1$。如果$x$的某一位为$1$,那么与$a$相应的位做减法后该位为$0$,异或运算得到的也是$0$。因此当$a$的所有位均为$1$时,$x$的任意一位都可以取$0$或$1$,因此$x$有$2^t$种($t$是$a$在二进制下$1$的位数)。
如果$a$在二进制下的位数不全为$1$,那么从低位向高位看,如果最低位为$1$,那么$x$在最低位取$0$和取$1$在减法和异或运算后该位得到的结果是一样的。接着从$a$的低位往高位看,找到第一个$0$,此时$x$在这一位取$0$是可以的,在减法和异或运算后得到的结果都是$0$。如果取$1$,对于减法运算一定会往高位借位,即往高位数的第一个$1$借位,假设这一个位是第$k$位,此时如果$x$的第$k$取$0$,那么借位后$a$的第$k$位变成$0$,做减法后得到$0$,而异或运算得到的结果是$1$($a$的第$k$位为$1$,$x$的第$k$位为$0$)。而如果$x$的第$k$取$1$,做减法后得到$1$,异或运算得到的结果是$0$($a$的第$k$位为$1$,$x$的第$k$位为$1$)。因此对于$a$中为$0$的位$x$在该位不能填$1$,只能填$0$,而$a$中为$1$的位$x$在该位能填$0$或$1$且各个位相互独立,因此答案就是$2^t$。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() { 5 int tot; 6 cin >> tot; 7 while (tot--) { 8 int n; 9 cin >> n; 10 int cnt = 0; 11 while (n) { 12 cnt += n & 1; 13 n >>= 1; 14 } 15 cout << (1 << cnt) << '\n'; 16 } 17 18 return 0; 19 }
参考资料
AcWing 4617. 解方程(AcWing杯 - 周赛):https://www.acwing.com/video/4355/
标签:运算,非负,leq,异或,解方程,减法,位为 From: https://www.cnblogs.com/onlyblues/p/16704901.html