Powerful Ksenia | CF1438D 给你一个长度为
n
n
n 的序列
A
[
n
]
A[n]
A[n] 你最多能操作
n
n
n 次,每次选择三个位置
i
,
j
,
k
i,j,k
i,j,k,然后让这三个位置的值等于
A
[
i
]
⊕
A
[
j
]
⊕
A
[
k
]
A[i]\oplus A[j]\oplus A[k]
A[i]⊕A[j]⊕A[k] 问你,能否使序列中所有数字都相同?若能,给出一种方案
3
≤
n
≤
1
0
5
3\le n\le 10^5
3≤n≤105
1
≤
a
i
≤
1
0
9
1\le a_i\le 10^9
1≤ai≤109
思路
想法和构造都太差了,准备记录一下这类题 首先,我们能操作一次,让三个位置的值都相等 接下来,我们想一下剩下的要怎么取搞 因为
[
a
,
a
,
b
]
[a,a,b]
[a,a,b] 操作一次会变成
[
b
,
b
,
b
]
[b,b,b]
[b,b,b]
[
a
,
b
,
c
]
[a,b,c]
[a,b,c] 操作一次会变成
[
d
,
d
,
d
]
[d,d,d]
[d,d,d] 所以我们这么操作:[a,a,a,b,c,d,e,f,g]
→
\rightarrow
→[a,a,h,h,h,d,e,f,g]
→
\rightarrow
→[a,a,h,h,i,i,i,f,g]
→
\rightarrow
→[a,a,h,h,i,i,j,j,j] 然后倒着操作:[a,a,h,h,j,j,j,j,j]
→
\rightarrow
→[a,a,j,j,j,j,j,j,j]
→
\rightarrow
→[j,j,j,j,j,j,j,j,j] 容易看到,如果区间长度是奇数,我们一定可以使用这样的构造方法来满足要求。但是如果
n
n
n 是偶数呢?
我们有一个不变性质。考虑三个数
[
a
,
b
,
c
]
[a,b,c]
[a,b,c] ,有
k
=
a
⊕
b
⊕
c
k=a\oplus b\oplus c
k=a⊕b⊕c 我们进行操作之后,这三个数就变成了
[
k
,
k
,
k
]
[k,k,k]
[k,k,k] 然后,我们发现
k
⊕
k
⊕
k
=
k
k\oplus k\oplus k=k
k⊕k⊕k=k 仍然是成立的 也就是说不管我们怎么操作,这
n
n
n 个数的异或值都是不变的! 再返回去看原来
n
n
n 为奇数的情况,那个最后的
j
j
j 其实就是所有数的异或值
对于
n
n
n 偶数来说,如果我们最终变成的数是 [k,k,k,k,k,k] ,容易得到:不管
k
k
k 为多少,所有数的异或值必须为
0
0
0 换句话说,如果此时数的异或值非零,那么一定无解;否则,一定有解 有解的话,构造方法其实是和
n
n
n 为奇数时一样的,只不过我们最后一个数不去操作 因为根据奇数的操作方法, 我们最后一定会获得 [a,a,a,a,a,a,a,b] ,因为异或和为
0
0
0 ,所以此时一定
a
=
b
a=b
a=b
代码
时间复杂度:
O
(
n
)
O(n)
O(n)
#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;typedeflonglong ll;voidshow(){std::cerr << endl;}template<typename T,typename... Args>voidshow(T x,Args... args){std::cerr <<"[ "<< x <<" ] , ";show(args...);}constint MAX =1e5+50;constint MOD =1e9+7;constint INF =0x3f3f3f3f;const ll LINF =0x3f3f3f3f3f3f3f3f;constdouble EPS =1e-5;
ll aa[MAX];intmain(){int n;scanf("%d",&n);
ll res =0;for(int i =1;i <= n;++i){scanf("%lld",&aa[i]);
res ^= aa[i];}if((n &1)||(res ==0)){if(n %2==0)n--;printf("YES\n%d\n",(n-1)/2+(n-1)/2-1);// 其实就是 n-2for(int i =1;i <= n -2;i +=2){printf("%d %d %d\n",i,i+1,i+2);}for(int i = n -4;i >=1;i -=2){printf("%d %d %d\n",i,i+1,i+2);}}else{puts("NO");}return0;}/**
*/