Equations of Mathematical Magic题解

问题描述:
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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值