Powerful Ksenia(构造)
Problem statment
Ksenia has an array a a a consisting of n n n positive integers a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an.
In one operation she can do the following:
- choose three distinct indices i , j , k i, j, k i,j,k, and then
- change all of a i , a j , a k a_i, a_j, a_k ai,aj,ak to a i ⊕ a j ⊕ a k a_i \oplus a_j \oplus a_k ai⊕aj⊕ak simultaneously, where ⊕ denotes the bitwise XOR operation.
She wants to make all a i a_i ai equal in at most n n n operations, or to determine that it is impossible to do so. She wouldn’t ask for your help, but please, help her!
Input
The first line contains one integer n n n ( 3 ≤ n ≤ 1 0 5 3 \leq n \leq 10^5 3≤n≤105) — the length of a a a.
The second line contains n n n integers, a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 9 ) (1 \leq a_i \leq 10^9) (1≤ai≤109) — elements of a a a.
Output
Print YES or NO in the first line depending on whether it is possible to make all elements equal in at most n n n operations.
If it is possible, print an integer m m m ( 0 ≤ m ≤ n ) (0 \leq m \leq n) (0≤m≤n), which denotes the number of operations you do.
In each of the next mm lines, print three distinct integers i , j , k , i, j, k, i,j,k, representing one operation.
If there are many such operation sequences possible, print any. Note that you do not have to minimize the number of operations.
题意
给你长度为 n n n的数组 a a a,你能够进行下序操作 ( 最 多 n 次 ) (最多n次) (最多n次):
- 挑选一个三元组 ( i , j , k ) (i,j,k) (i,j,k)
- 然后是 a i a_i ai= a j a_j aj= a k a_k ak= a i ⊕ a j ⊕ a k a_i \oplus a_j \oplus a_k ai⊕aj⊕ak
使得 a a a数组中每个元素都相同,如果能,输出“ Y E S YES YES”,并输出操作数和按顺序输出选择的三元组,如果不能输出" N O NO NO"
思路
我们可以发现进行如下操作:
- 选择 ( 1 , 2 , 3 ) (1,2,3) (1,2,3), a 1 = a 2 = a 3 = a 1 ⊕ a 2 ⊕ a 3 a_1=a_2=a_3=a_1 \oplus a_2 \oplus a_3 a1=a2=a3=a1⊕a2⊕a3
- 随后选择 ( 3 , 4 , 5 ) (3,4,5) (3,4,5),此时的 a 3 a_3 a3经过上述操作已经变成了 a 1 ⊕ a 2 ⊕ a 3 a_1 \oplus a_2 \oplus a_3 a1⊕a2⊕a3,那么在进行这步操作的时候 a 3 = a 4 = a 5 = a 3 ⊕ a 4 ⊕ a 5 a_3=a_4=a_5=a_3 \oplus a_4 \oplus a_5 a3=a4=a5=a3⊕a4⊕a5即 a 3 = a 4 = a 5 = a 1 ⊕ a 2 ⊕ a 3 ⊕ a 4 ⊕ a 5 a_3=a_4=a_5=a_1 \oplus a_2 \oplus a_3 \oplus a_4 \oplus a_5 a3=a4=a5=a1⊕a2⊕a3⊕a4⊕a5
- 那么我们一直模仿上序操作一直取到 n − 2 n-2 n−2位为止,每步加 2 2 2,那么 a n = a n − 1 = a n − 2 = a 1 ⊕ a 2 ⊕ a 3 ⊕ ⋯ ⊕ a n a_n=a_{n-1}=a_{n-2}= a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_n an=an−1=an−2=a1⊕a2⊕a3⊕⋯⊕an(奇数). a n − 1 = a n − 2 = a n − 3 = a 1 ⊕ a 2 ⊕ a 3 ⊕ ⋯ ⊕ a n − 1 a_{n-1}=a_{n-2}=a_{n-3}= a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_{n-1} an−1=an−2=an−3=a1⊕a2⊕a3⊕⋯⊕an−1(偶数),因为我是从 1 1 1开始枚举的,每次枚举两位,也就是说我 n n n为奇数的时候,枚举到最多的位置为 n − 2 n-2 n−2位,偶数的话为 n − 3 n-3 n−3
- 这时候我们就发现了我们进行上述操作时,如 1 , 2 1,2 1,2两步时, a 1 = a 2 a_1=a_2 a1=a2,同时 a 3 = a 4 a_3=a_4 a3=a4,就是每进行一步操作必有相邻的两个数相等。
因此,得到结论:
- 如果为奇数,一定能行,我们先模仿 1 , 2 1,2 1,2两步操作,一直取到 n − 2 n-2 n−2为止,每次加 2 2 2,然后每次去那两个相邻的数,与 a n a_n an进行异或就行了,总操作数为 ( n − 3 ) / 2 + 1 + ( n − 1 ) / 2 (n-3)/2+1 + (n-1)/2 (n−3)/2+1+(n−1)/2
- 如果为偶数的话,由于我们最后一位 a n a_n an没有进行任何操作,因此,我们要判断 a n a_n an是否等于 a n − 1 = a n − 2 = a n − 3 = a 1 ⊕ a 2 ⊕ a 3 ⊕ ⋯ ⊕ a n − 1 a_{n-1}=a_{n-2}=a_{n-3}= a_1 \oplus a_2 \oplus a_3 \oplus \dots \oplus a_{n-1} an−1=an−2=an−3=a1⊕a2⊕a3⊕⋯⊕an−1就是数组整体异或是否为 0 0 0就行,如果为 0 0 0说明能够构造,模仿上述操作。如果不为 0 0 0,就一定构造不出来。
代码
#include<bits/stdc++.h>
#define Case int t;scanf("%d",&t);while(t--)
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int M=1e6+10;
ll a[N];
struct node{
int a,b,c;
}ans[N];
void run(){
int n;
scanf("%d",&n);
int num=0;
ll sum=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum^=a[i];
}
if(n%2==0&&sum){
printf("NO\n");
return ;
}
printf("YES\n");
for(int i=1;i<=n-2;i+=2){
ans[++num].a=i;
ans[num].b=i+1;
ans[num].c=i+2;
}
for(int i=1;i<n-1;i+=2){
ans[++num].a=i;
ans[num].b=i+1;
ans[num].c=n;
}
printf("%d\n",num);
for(int i=1;i<=num;i++){
printf("%d %d %d\n",ans[i].a,ans[i].b,ans[i].c);
}
}
int main(){
// Case
run();
return 0;
}
道阻且长,且行且珍惜