CodeForces-1438D-Powerful Ksenia

108 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目大意:

在这里插入图片描述

有一个长度为n的数组a,每次选择三个数字aia_i ^aja_j ^aka_k,使得最后n个数字都相等。如果存在就输出“YES”,并且输出操作次数m,再输出m行,每行是操作的数的下标;否则就输出“NO”

思路:

先考虑n为奇数的情况。假设n-1个数字两两相等,那么就剩余一个数字未配对,每次将这个数字(假设下标为i)aia_i 与那n-1个数字中的任意两个进行异或,最后都可以变成aia_i 。如何将这n-1个数字两两相等?假设那个未配对的数字是ana_n ,那么之间的1~n-1个数字可以三个为一组进行异或,前一组将aia_i ,ai1a_{i-1} ,ai2a_{i-2}进行异或,当前这组将aia_i ,ai+1a_{i+1} ,ai+2a_{i+2}进行异或.这样操作就可以将前n-1个数字两两配对相等。最后两两配对的数字再都与最后一个数字an进行异或就可以将n个数字都变成an。

那如何考虑n为偶数的情况?

n为偶数的时候,将数组a全部进行异或之后,假设可以实现最后全部相等,那么异或的结果就是0.假设当前对aia_i,aja_j,aka_k异或,那么aia_i=aja_j=aka_k=aia_i ^ aja_j ^ aka_k.那么此时再对aia_i,aja_j,aka_k异或,aia_{i'} ^ aja_{j'} ^ aka_{k'}=(aia_i ^ aja_j ^ aka_k)(aia_i ^ aja_j ^ aka_k)(aia_i ^ aja_j ^ aka_k),这样其实和原来是相等的。所以a数组最初的所有数字异或的结果=a数组最终结果的所有数字异或结果,最终由于a数组全部相等,那么a数组的异或结果就是0,即a数组的最初异或结果是0.我们将前n-1个数字当作奇数进行处理,就可以将前n-1个数字都变成ana_n。因为前n-1个的异或结果=ana_n,而前n-1个当作奇数情况进行上述情况一进行处理都变成了相同的数,显然最后都变了ana_n

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+50;
typedef long long ll;
int n,a[maxn],cnt;
struct Node{
	int x,y,z;
}t[maxn];
int main(){
	cin>>n;
	int x=0;
	for(int i=1;i<=n;i++)cin>>a[i],x^=a[i];
	sort(a+1,a+1+n);
	if(n%2){
		cout<<"YES"<<endl;
		for(int i=1;i+2<=n;i+=2){
			cnt++;t[cnt].x=i;t[cnt].y=i+1;t[cnt].z=i+2;
		}
		for(int i=1;i+1<=n-1;i+=2){
			cnt++;t[cnt].x=i;t[cnt].y=i+1;t[cnt].z=n;
		}
		cout<<cnt<<endl;
		for(int i=1;i<=cnt;i++){
			cout<<t[i].x<<' '<<t[i].y<<' '<<t[i].z<<endl;
		}
	}
	else{
		if(x){
			cout<<"NO"<<endl;
		}
		else{
			cout<<"YES"<<endl;
			n--;
			for(int i=1;i+2<=n;i+=2){
				cnt++;t[cnt].x=i;t[cnt].y=i+1;t[cnt].z=i+2;
			}
			for(int i=1;i+1<=n-1;i+=2){
				cnt++;t[cnt].x=i;t[cnt].y=i+1;t[cnt].z=n;
			}
			cout<<cnt<<endl;
			for(int i=1;i<=cnt;i++){
				cout<<t[i].x<<' '<<t[i].y<<' '<<t[i].z<<endl;
			}
		}
	}
	return 0;
}