CodeForces - Ehab the Xorcist(思维/构造)

本文解析了Codeforces竞赛题1325/D,介绍了如何利用位运算技巧解决u与v的关系,通过分类讨论、构造方法找出最短数组,满足异或和等于u且和等于v的条件。关键步骤包括理解奇偶性规律和利用异或性质简化答案。
摘要由CSDN通过智能技术生成

传送门:https://codeforces.com/problemset/problem/1325/D

题面:

在这里插入图片描述

题意:

给出u,v,求一个长度最短的数组使得:
a 1 ⊕ a 2 ⊕ . . . . . . ⊕ a n = u a_1⊕a_2⊕......⊕a_n=u a1a2......an=u--------------------①
a 1 + a 2 + . . . . . . + a n = v a_1+a_2+......+a_n=v a1+a2+......+an=v--------------------②

思路:

这道题需要对位运算非常了解才能找到u,v之间的相对规律
我们对u,v分情况讨论

  1. u>v:n个数的异或和不可能大于这n个数的和,直接排除输出"-1"
  2. (v-u)%2==1: 实际上v和u的奇偶性是相同的,那么他们的差值不可能是奇数,输出"-1"
    下面简单分析一下
    假设①式中有x个奇数,剩下n-x个偶数,它们的异或和为偶数
    那么u的奇偶性就取决于这x个奇数的异或和(奇数⊕偶数=奇数、偶数⊕偶数=偶数)
    当x为奇数时:
     x个奇数的异或和为奇数(理解为x个1的异或和),得到的u为奇数,
     x个奇数相加结果也为奇数,加上n-x个偶数,得到的v也为奇数
    当x为偶数时同理
  3. u=v: 结果数组只有一个值,就是u或v
  4. u=0:也容易得到结果数组就是v/2,v/2,因为相同的两个数异或和为0,v=0的情况已经在3.u=v里讨论过了
  5. 剩下的情况需要用构造法解决,已知u⊕0=0,k⊕k=0,那么:
    u⊕k⊕k=u
    u+k+k=v
    可以得到k=(v-u)/2,最多可以解出长度为3的答案数组,也就是 u,(v-u)/2,(v-u)/2
    但题目要求得是最短的数组,所以还需要在可以缩短的情况下继续构造化简,可以这样构造
    (u+k)⊕k=u,也就是使 u⊕k⊕k=(u+k)⊕k
    即满足 u⊕k=u+k的条件下,答案数组可以由两个数构成u+k,k
    这里有用到一个结论:a⊕b=a+b => a&b=0
    带入k=(v-u)/2得u&((v-u)/2)=0

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll u,v;
int main() {
	cin>>u>>v;
	//分类讨论
	if(u>v || (v-u)&1) cout<<-1<<endl;
	else if(u==0) {
		if(v==0) cout<<0;
		else cout<<2<<endl<<v/2<<" "<<v/2<<endl;
	}
	else if(u==v) cout<<1<<endl<<u<<endl;
	else if(u&(v-u)/2) {
		cout<<3<<endl;
		cout<<u<<' '<<(v-u)/2<<' '<<(v-u)/2;
	} else {
		cout<<2<<endl;
		cout<<u+(v-u)/2<<' '<<(v-u)/2;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值