问题描述:
Colossal! — exclaimed Hawk-nose. — A programmer! That’s exactly what we are looking for.
Arkadi and Boris Strugatsky. Monday starts on Saturday
Reading the book “Equations of Mathematical Magic” Roman Oira-Oira and Cristobal Junta found an interesting equation: a−(a⊕x)−x=0a−(a⊕x)−x=0 for some given aa, where ⊕⊕stands for a bitwise exclusive or (XOR) of two integers (this operation is denoted as ^ or xor in many modern programming languages). Oira-Oira quickly found some xx, which is the solution of the equation, but Cristobal Junta decided that Oira-Oira’s result is not interesting enough, so he asked his colleague how many non-negativesolutions of this equation exist. This task turned out to be too difficult for Oira-Oira, so he asks you to help.
Input
Each test contains several possible values of aa and your task is to find the number of equation’s solution for each of them. The first line contains an integer tt (1≤t≤10001≤t≤1000) — the number of these values.
The following tt lines contain the values of parameter aa, each value is an integer from 00 to 230−1230−1 inclusive.
Output
For each value of aa print exactly one integer — the number of non-negative solutions of the equation for the given value of the parameter. Print answers in the same order as values of aa appear in the input.
One can show that the number of solutions is always finite.
Example
Input
3
0
2
1073741823
Output
1
2
1073741824
题解:
首先
题目可以简单地描述为:
求 a - x = a^x的解的个数 其中 ^ 为位运算符 异或
a为输入 x为所需的解
在草稿上列列看 能否找到内在联系
**
**
首先取a = 10 然后以 x = 1 代入观察对比 a - x = a^x 左右边变化情况
**
**
为了方便描述,我们规定: 二进制位中 对应位表示的大小即为 该位的值*2位数-1
10的二进制 1010
1的二进制 0001
考虑左边减法运算结果: 10减去 1 二进制位等于1的位(该例为低阶位)表示的大小
再去其他数字例如5 : 0101
同样 结果为:10减去 5二进制位等于1的位(在此例为 第 1、3位)表示的大小
重点考虑右边:1010
0001
结果: 1011 根据异或运算规律
1.上0 下1 => 1 局部结果为加上对应位表示的大小
2.上1 下1 => 0 局部结果为减去对应位表示的大小
3.上0 下0 =>0 局部不变
4.上1 下0 =>1 局部不变
发现 2. 的情况与左边运算结果一致!
下0的情况 局部结果保持不变
上0的情况 必须下0才能保持不变
因此我们得到一个结论:
所有(记住是所有)对应位 a为1 b也为1 时 a^b = a - b
于是乎 我们要 a - x = a^x 成立
只需要满足 x的对应位为1 而a的对应位也为1
x的对应位为0 则a对应位任取1或0
例如 a: 1010
x1: 1000
x2:0010
x3:1010
x4:0000 都满足以上条件
进一步体会 也就是说 a为1的位 x可任取0或1
a为0的位 x绝对不可取1
那么问题就转化为了一个很简单的排列组合问题
假设a的1的位共有 m个 求x的二进制组合个数
那么显然 x的组合个数有 2m 个
经过一番推导 原来繁琐的题目 代码只要堪堪数行…
这就是数学和推理的重要性了
#include<bits/stdC++.h>
using namespace std;
int main()
{
int t = 0,cnt = 0; //cnt表示a中为1的二进制位的个数
long long a = 0;
cin >> t;
while(t--)
{
cin >> a;
for(cnt = 0;a;a >>= 1)
{
if(a&1) cnt++;
}
cout << (long long )pow(2,cnt) << endl;
}
return 0;
}
萌新不容易
如有错误请多多包涵 多多指教
补充:
判断a的二进制数中 位等于1的个数可以直接
__builtin_popcount(a) // a为32位整数
__builtin_popcountll(a) // a为long long 64位
同理
__builtin_clz(a)
__builtin_clzll(a)