[Daimayuan] 简单的异或问题(C++,数学)
有一组整数 {0,1,2,…,2m−1}\\{0,1,2,…,2_{m−1}\\}{0,1,2,…,2m−1}, 请从中选出 kkk 个数,使得这 kkk 个数的异或和为 nnn, 请输出最大的满足条件的 kkk。
输入格式
两个数 nnn 和 mmm, 其中 0≤n≤2m−1,1≤m≤600≤n≤2m−1,1≤m≤600≤n≤2m−1,1≤m≤60。
输出格式
输出最大的满足条件的 kkk。
样例输入
2 2
样例输出
3
样例解释
对于样例,我们可以选择 0,1,3{0,1,3}0,1,3。
解题思路
首先介绍一下异或和:
异或操作:同则为假,不同为真
1^0=1
0^1=1
0^0=0
1^1=0
给定两个数,这里以888和444为例,其异或和
0000 1000
0000 0100
---------
0000 1100
接下来是解题思路:
这里先列出来一部分二进制格式的数字
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10
1011 11
1100 12
1101 13
1110 14
1111 15
然后我们可以发现:任意数量大于111的000与相同数量的111作异或操作,无论顺序,结果均为000
再进一步看到:当m>1m>1m>1时,000~2m−12^m-12m−1之内的所有数的异或和为000
那么当m>1m>1m>1时,我们想得到任意数字n∈[0,2m−1]n \\in [0, 2^m-1]n∈[0,2m−1]且n≠0n \\ne 0n=0,只需要从异或和中去掉nnn即可
当m=1m=1m=1时,我们进行特殊判定即可
AC代码如下
#include <iostream>
using namespace std;int main() {long long n, m;cin >> n >> m;if (m == 1) {if (n) cout << 2 << endl;else cout << 1 << endl;}else {if (!n) cout << (1LL << m) << endl;else cout << ((1LL << m) - 1) << endl;}return 0;
}