题意:
让你输出一个长度为 n 的数组,这个数组所有元素异或和要等于 x。
题解:
首先我们要知道:x ^ y ^ (x ^ y) = 0,这样我们就可以推出:x ^ y ^ (x ^ y ^ z) = z => x ^ y ^ z ^ (x ^ y ^ z ^ m) = m。
因此,我们可以通过这样去构造一个数组,假如:1,2,...,n - 3,保留后三位,前面从 1 到 n - 3 输出,该异或和为Z。则Z ^ X ^ Y ^ (X ^ Y ^ Z ^ x) = x,因为元素不能超过 1e6(20位)并且 x <= 1e5,所以 X 和 Y 取17 18 19 位为0都可以,我选择取了 X = 1 << 17,Y = 1 << 18。
这里为什么取 x ^ y ^ z ^ (x ^ y ^ z ^ m) = m 这条公式,而不是 x ^ y ^ (x ^ y ^ z) = z,因为前面异或和可能就已经等于 x 了,会导致最后一位和最后第二位一样的可能,所以不能选取。我们选取的公式可以保证最后一个数和前面的数不一样,因为有两位一定为 1,无论 1 到 n - 3 异或和是不是为 x 都无所谓。
AC代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1000+10;
int main() {
int n, x;
while(cin >> n >> x) {
if(n == 1) {
cout << "YES" << endl << x << endl;
} else if(n == 2) {
if(x == 0) {
cout << "NO" << endl;
} else {
cout << "YES" << endl << 0 << " " << x << endl;
}
} else {
cout << "YES" << endl;
int X = 1 << 17, Y = 1 << 18, Z = 0;
for(int i = 1; i <= n - 3; i++) {
cout << i << " ";
Z ^= i;
}
cout << X << " " << Y << " " << (X ^ Y ^ Z ^ x) << endl;
}
}
}