题目传送门
题解
-
u:相加和,v:异或和
- 在二进制运算中,对于某一位来讲:
a∧b:表示a+b的本位
a & b:表示a+b应该进的位
- 那么
a & b<<1:表示进位之后
- 所以
a+b=(a∧b) + 2∗(a & b)
- 同理,对于一个二进制运算也是一样的。
- 带入本题:
v=u+2∗(a & b)
- 情况一:
u>v 或 (v−u)%2==1
这两种情况都是不满足上面等式,属于非法输入,直接输出-1
- 情况二:
u==v
-
v==0,这是空数组的情况,输出0
-
v !=0,说明数组只有一个元素,输出
u
- 接下来我们就需要认真分析了。
- 设
d=(v−u)/2=a & b
- 我们可以构造特殊数组,因为相同的两个数异或值等于0,所以可以构造出
u∧ 0=u,这个
0 是由两个
d 组成的,也就是数组为
[u,d,d]。
- 我们来验证一下:
u+d+d=u+(v−u)=v
u∧d∧d=u
符合题意!也就是说,最多三个元素就可以满足题意。
- 让我们继续思考能否继续缩减成
2 个元素
样例已经告诉我们了
- 我们试着从当前答案进行转化,把其中一个
d 和
u 合并。也就是
[d,u+d]
- 我们来验证一下:
d+u+d=v
d∧(u+d)=((v−u)/2)∧(u+(v−u)/2)=((v−u)/2)∧((v+u)/2)
【emmm,好像看不出什么】
- 换个思路,我们知道
[u,d,d]一定是对的,那么我们把
u,d合并为一个u+d,就是在找这种情况满足的条件。
- 回顾通解:
[u,d,d]
u∧d∧d=u
- 再看特解
d∧(u+d)= ?
- 如果想要这两个式子等价,也就是特解,那么需要保证
u+d==u∧d
- 至此,我们已经分析完了所有的情况。
- 总结一下后两种情况:
- 情况三: 通解
[u,d,d]
- 情况四: 当
u+d==u∧d 的时候,特解
[u+d,d]
- 情况四的特解条件可以继续化简,步骤如下:
因为
a+b=(a∧b) + 2∗(a & b)
带入
u和d:
u+d=(u∧d) + 2∗(u & d)
等价于
u & d==0
- 到这里,就没有什么其他的东西了,顺便说一下,这道题是 Codeforces 1325 D. Ehab the Xorcist 的 原题
AC-Code
#include <bits/stdc++.h>
using namespace std;
int main() {
int u, v;
while(cin >> u >> v) {
if(u > v || ((v - u) & 1)) {
cout << -1 << endl;
continue;
}
if(u == v) {
if(v)
cout << 1 << endl;
else
cout << 0 << endl;
continue;
}
int d = (v - u) / 2;
if(d & u) {
cout << 3 << endl;
}
else {
cout << 2 << endl;
}
}
}