CF1438D Powerful Ksenia

题解

异或性质

1^1=0
1^0=1
0^1=1
0^0=0

简单来说,同为0,异为1

模拟

操作:任意三个数可以变成这三个数异或和
目的:使序列都相同
可以尝试先模拟

当n=3时 直接进行1次操作
当n=4时
[x,y,z,w]
1次操作后
设s=x ^ y ^ z
[s,s,s,w]
此时 任意选三个数要么是 s,s,w或s,s,s
选s,s,s没有意义,s,s,w,则又等于w,w,w,此时[s,w,w,w]
接下来无论怎么操作,这个序列的数都不能想等
但当s=w时 序列即可相等 则当s!=w时 无论多少次操作皆不可能
当n=5时
[x,y,z,w,u]
1次操作,选前三个数
设s=x ^ y ^ z
[s,s,s,w,u]
2次操作,如果选s,s,w没有意义因为选了两个s,s只会把这个三个数又变成那个除了s的数
此时我们能选的三个数s,w,u
设k=s ^ w ^ u
操作后
[s,s,k,k,k]
耶 突然发现 这个时候 把s,s,k 一操作
3次操作
[k,k,k,k,k]
这个时候还没发现什么
继续啊
当n==6时
[a,b,c,d,e,f]

经过类似 当n==5时的序列操作

[k,k,k,k,k,f]
此时类比n=3 和 n=4

当k==f时 仍有解

经过这几次模拟后

会发现当n为奇数时 一定有解
当n为偶数时 前n-1位数异或相同后的数与第n个数时,有解 否则无解

通过之前的模拟会发现
s ^ s ^ k =k(当然其实也是异或的性质
所以再看 n为奇数时 ( n − 1 ) m o d = = 0 (n-1) mod ==0 (n1)mod==0
则可以考虑 把n-1长度的序列 分为 n − 1 2 \frac{n-1} {2} 2n1个区间并使这个区间内数相同

那么目前的任务,使区间内的数相等
例如 [a,b,c,d,e,f,g] ——> [h,h,j,j,k,k,k]

[a,b,c,d,e,f,g]——>[h,h,h,d,e,f,g]——>[h,h,j,j,j,f,g]——>[h,h,j,j,k,k,k]
接下来再把任意区间和第n个数异或
[h,h,j,j,k,k,k]——>[k,k,j,j,k,k,k]——>[k,k,k,k,k,k,k]
可推k==j ^ f ^ g=h ^ d ^ e ^ f ^g=a ^ b ^ c ^ d ^ e ^ f ^ g
推广一下
当n为奇数时
先把每个区间内数相等 需要 n − 1 2 \frac{n-1}{2} \quad 2n1次操作
再把 n − 3 2 \frac{n-3}{2}\quad 2n3次数操作
总次数 n − 3 2 + n − 1 2 = n − 2 \frac{n-3}{2}\quad+\frac{n-1}{2}\quad=n-2 2n3+2n1=n2

当n为偶数时
则其操作与奇数 n − 1 n-1 n1几乎相同
加一个判断 是否前 n − 1 n-1 n1个异或和是否与第n个相同
即前n-1项异或 与 第n个数异或 等于 0

code

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;
int n;int sum=0;
const int maxn=1e5+10;
int a[maxn];
int main(){
	cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i],sum^=a[i];
	if(!(n&1)) {//当n为偶数 
		if(sum){//前n-1位可当成n为奇数数时操作
				//当且仅当第n位的数等于前(n-1)位异或成的数,此时sum=0 
				//偶数个按位异或的数相同 
			cout<<"NO"<<endl;
			return 0;}
		--n;
	}
	cout<<"YES"<<endl;
	cout<<n-2<<endl;
	for(int i=1;i<=n-2;i+=2) cout<<i<<" "<<i+1<<" "<<i+2<<endl;//使i,i+1位上的数相等,i%2==1 
	//使整个序列等于n,经过第一轮操作,n-2,n-1,n位上的数字都相等
	//i只用循环到n-4位即可 
	for(int i=1;i<=n-4;i+=2) cout<<i<<" "<<i+1<<" "<<n<<endl;
	return 0; 
} 

总结

本质是一道构造题

  • 异或性质要清楚
  • 尝试模拟计算过程
  • 归纳
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值