CodeForces - 862C(构造)

题意:

让你输出一个长度为 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;
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章