解方程

解方程

给定一个非负整数 $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/

posted @ 2022-09-18 15:43  onlyblues  阅读(159)  评论(0编辑  收藏  举报
Web Analytics