CF1438D Powerful Ksenia(构造题)
洛谷传送门
解题思路
很经典的一个构造题。
从异或的性质入手:a^a^b=b。
于是我们就有了将其变成同一个数的一个策略:
若原来能化成aabbccc这样的一个数列,则可以在345、123位置依次进行一次操作,将其全部变为c。
而这个数列的形式也很容易达到。
从前往后以此在123、345、567进行一次操作即可。
当然这是奇数的情况,一定有解。
偶数却不一定有解。
还是用上述方法,我们发现最后会剩下一个元素。
所以当剩下的最后一个元素等于前面的元素,则一定有解。
这是只需要处理前n-1个数,当做奇数情况来做即可。
如何判断偶数情况是否有解呢?
我们发现当把三个数都变成其异或和时,整个数列的异或和是没有变的。
所以当偶数个数字时,若整个序列的异或和为0,则有解,否则无解。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
int n,a[maxn],cnt,ans[maxn][4];
long long sum;
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],sum^=a[i];
if((n&1)==0&&sum!=0){
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
if((n&1)==0) n--;
for(int i=1;i<=n-2;i+=2){
ans[++cnt][1]=i;
ans[cnt][2]=i+1;
ans[cnt][3]=i+2;
}
for(int i=n-2;i>=3;i-=2){
ans[++cnt][1]=i;
ans[cnt][2]=i-1;
ans[cnt][3]=i-2;
}
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++){
cout<<ans[i][1]<<" "<<ans[i][2]<<" "<<ans[i][3]<<endl;
}
return 0;
}