题目
题目链接:https://codeforces.ml/problemset/problem/1438/D
给 (n) 个正整数 (a_i),(1 le a_ile10^9)。
每次操作是选三个不同的下标 (i,j,k) ,让 (a_i,a_j,a_k) 都变成 (a_i oplus a_joplus a_k) 也就是这三个数的异或和。
让你判断是否能在 (n) 次操作内,使这 (n) 个正整数的值变成相同的。
若能,第一行输出YES,第二行输出 (m) 表示操作数两,接下来 (m) 行每行三个整数,描述一次操作;
若不能,输出NO。
思路
由于 (aoperatorname{xor} boperatorname{xor} b=a),所以当 (n) 是奇数的时候,考虑将序列变为 (frac{n-1}{2}) 个两两相等的数,再将他们全部异或上最后一个数。
那么我们每次取任意三个数异或起来,将其中两个放做一组,剩余一个扔进序列中继续搞,这样就可以在 (frac{n-1}{2}) 次操作达到目标。最后异或成同一个数仍然需要 (frac{n-1}{2}) 次操作,总操作数为 (n-1) 次。
当 (n) 是偶数的时候,因为进行任意操作序列的异或和仍然不变,所以最终如果有解,序列异或和一定是 (0)。
所以如果原序列异或和不为 (0) 直接无解,否则我们可以先将前 (n-1) 个数字按照奇数的方式做好,第 (n) 个数字最终一定等于第 (n-1) 个数字。操作次数为 (n-2)。
时间复杂度 (O(n))。
代码
#include <bits/stdc++.h>
using namespace std;
int n,xors;
int main()
{
scanf("%d",&n);
for (int i=1,x;i<=n;i++)
{
scanf("%d",&x);
xors^=x;
}
if (!(n&1) && xors) return printf("NO"),0;
if (!(n&1)) n--;
printf("YES
%d
",n-1);
for (int i=1;i<=n-2;i+=2)
printf("%d %d %d
",i,i+1,i+2);
for (int i=1;i<=n-2;i+=2)
printf("%d %d %d
",i,i+1,n);
return 0;
}