codeforces round743 D xor of 3

题目链接

题意

给出一个长度为n的01序列,每次操作可以选择一个位置\(i\),然后将\(a_i,a_{i + 1},a_{i + 2}\)均变成\(a_i \otimes a_{i + 1} \otimes a_{i + 2}\),找出一种操作方式,使得用不超过n次操作可以把整个序列变成0。如果不存在就输出NO

思路

显然只有当有偶数个1时才可能有解。

如果n是奇数,那就依次对\(a_1,a_3...a_{n-2}\)进行操作,因为有偶数个1,而最后三个数相当于是整个序列异或起来,所以\(a_n=a_{n-1}=a_{n-2}=0\),而且这样可以使得\(a_i=a_{i+1}\),然后只要依次对\(a_{n-4},a_{n-6}...a_1\)进行操作即可。

如果n是偶数,那就把这个序列拆成两个长度为奇数且异或和为0的序列,然后用上面的方法。如果不存在一种拆法满足上述条件,那么就一定无解。

代码

/*
* @Author: wxyww
* @Date: 2021-09-23 10:02:41
* @Last Modified time: 2021-09-23 15:15:07
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 200010;
ll read() {
	ll x=0,f=1;char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
int a[N],ans[N],cnt;
void solve(int l,int r) {
	for(int i = l;i < r;i += 2) ans[++cnt] = i;
	for(int i = r - 4;i >= l;i -= 2) ans[++cnt] = i;
}
int main() {
	int T = read();
	while(T--) {
		cnt = 0;
		int n = read();
		int tmp = 0;
		for(int i = 1;i <= n;++i) {
			a[i] = read();
			tmp ^= a[i];
		}
		if(tmp) {
			puts("NO");continue;
		}
		if(n & 1) solve(1,n);
		else {
			int k = 0,bz = 0;;
			for(int i = 1;i <= n;i += 2) {
				k ^= a[i] ^ a[i - 1];
				if(!k) {
					solve(1,i);solve(i + 1,n);
					bz = 1;break;
				}
			}
			if(!bz) {
				puts("NO");continue;
			}
		}
		puts("YES");
		printf("%d\n",cnt);
		for(int i = 1;i <= cnt;++i) printf("%d ",ans[i]);
		puts("");

	}
	return 0;
}

/*

3
5
1 1 1 1 0
4
1 0 0 1
*/

posted @ 2021-09-23 15:29  wxyww  阅读(63)  评论(0编辑  收藏  举报