传送门:https://codeforces.com/problemset/problem/1325/D
题面:
题意:
给出u,v,求一个长度最短的数组使得:
a
1
⊕
a
2
⊕
.
.
.
.
.
.
⊕
a
n
=
u
a_1⊕a_2⊕......⊕a_n=u
a1⊕a2⊕......⊕an=u--------------------①
a
1
+
a
2
+
.
.
.
.
.
.
+
a
n
=
v
a_1+a_2+......+a_n=v
a1+a2+......+an=v--------------------②
思路:
这道题需要对位运算非常了解才能找到u,v之间的相对规律
我们对u,v分情况讨论
- u>v:n个数的异或和不可能大于这n个数的和,直接排除输出"-1"
- (v-u)%2==1: 实际上v和u的奇偶性是相同的,那么他们的差值不可能是奇数,输出"-1"
下面简单分析一下
假设①式中有x个奇数,剩下n-x个偶数,它们的异或和为偶数
那么u的奇偶性就取决于这x个奇数的异或和(奇数⊕偶数=奇数、偶数⊕偶数=偶数)
当x为奇数时:
x个奇数的异或和为奇数(理解为x个1的异或和),得到的u为奇数,
x个奇数相加结果也为奇数,加上n-x个偶数,得到的v也为奇数
当x为偶数时同理 - u=v: 结果数组只有一个值,就是u或v
- u=0:也容易得到结果数组就是v/2,v/2,因为相同的两个数异或和为0,v=0的情况已经在3.u=v里讨论过了
- 剩下的情况需要用构造法解决,已知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;
}
}