有一组整数 { 0 , 1 , 2 , … , 2 m − 1 } \{0,1,2,…,2_{m−1}\} {0,1,2,…,2m−1}, 请从中选出 k k k 个数,使得这 k k k 个数的异或和为 n n n, 请输出最大的满足条件的 k k k。
两个数 n n n 和 m m m, 其中 0 ≤ n ≤ 2 m − 1 , 1 ≤ m ≤ 60 0≤n≤2m−1,1≤m≤60 0≤n≤2m−1,1≤m≤60。
输出最大的满足条件的 k k k。
2 2
3
对于样例,我们可以选择 0 , 1 , 3 {0,1,3} 0,1,3。
首先介绍一下异或和:
异或操作:同则为假,不同为真
1^0=1
0^1=1
0^0=0
1^1=0
给定两个数,这里以 8 8 8和 4 4 4为例,其异或和
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
然后我们可以发现:任意数量大于 1 1 1的 0 0 0与相同数量的 1 1 1作异或操作,无论顺序,结果均为 0 0 0
再进一步看到:当 m > 1 m>1 m>1时, 0 0 0~ 2 m − 1 2^m-1 2m−1之内的所有数的异或和为 0 0 0
那么当 m > 1 m>1 m>1时,我们想得到任意数字 n ∈ [ 0 , 2 m − 1 ] n \in [0, 2^m-1] n∈[0,2m−1]且 n ≠ 0 n \ne 0 n=0,只需要从异或和中去掉 n n n即可
当 m = 1 m=1 m=1时,我们进行特殊判定即可
AC代码如下
#include
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;
}