本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目大意:
有一个长度为n的数组a,每次选择三个数字 ^ ^,使得最后n个数字都相等。如果存在就输出“YES”,并且输出操作次数m,再输出m行,每行是操作的数的下标;否则就输出“NO”
思路:
先考虑n为奇数的情况。假设n-1个数字两两相等,那么就剩余一个数字未配对,每次将这个数字(假设下标为i) 与那n-1个数字中的任意两个进行异或,最后都可以变成 。如何将这n-1个数字两两相等?假设那个未配对的数字是 ,那么之间的1~n-1个数字可以三个为一组进行异或,前一组将 , ,进行异或,当前这组将 , ,进行异或.这样操作就可以将前n-1个数字两两配对相等。最后两两配对的数字再都与最后一个数字an进行异或就可以将n个数字都变成an。
那如何考虑n为偶数的情况?
n为偶数的时候,将数组a全部进行异或之后,假设可以实现最后全部相等,那么异或的结果就是0.假设当前对,,异或,那么=== ^ ^ .那么此时再对,,异或, ^ ^ =( ^ ^ )( ^ ^ )( ^ ^ ),这样其实和原来是相等的。所以a数组最初的所有数字异或的结果=a数组最终结果的所有数字异或结果,最终由于a数组全部相等,那么a数组的异或结果就是0,即a数组的最初异或结果是0.我们将前n-1个数字当作奇数进行处理,就可以将前n-1个数字都变成。因为前n-1个的异或结果=,而前n-1个当作奇数情况进行上述情况一进行处理都变成了相同的数,显然最后都变了。
代码:
#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;
}