题目大意
给出 u u u 和 v v v两个数,需要构造出最短的且异或和为 u u u,和为 v v v 的序列.
分析
(分析均在二进制下)
先考虑不存在的情况,可以发现如果 u > v u>v u>v 显然是不存在的,在考虑每加入一个新的数,如果是奇数,那么异或和最后一位会异或上 1 1 1,和的最后一位也会异或上 1 1 1,如果加的偶数则最后后一位不会变化,所以必须 u u u 和 v v v 奇偶性相同时才会有答案.
(下面的分析中有一个很重要的结论: ∀ a ∈ Z ∃ a ⊕ a = 0 \forall a \in \mathbb{Z}\ \exists\ a \oplus a=0 ∀a∈Z ∃ a⊕a=0)
如果 u u u 为 0 0 0,如果 v v v 也是 0 0 0,则直接输出 0 0 0,否则 v v v 一定是偶数,所以可以将它拆成两个 v 2 \frac{v}{2} 2v.
如果 u u u 不为 0 0 0,考虑拆除三个数 u , v − u 2 , v − u 2 u,\frac{v-u}{2},\frac{v-u}{2} u,2v−u,2v−u,三个数的和为 v v v,且三个数为异或和为 u u u,但是这并不意味着一定是三个数,如果 ( u + v − u 2 ) ⊕ v − u 2 = u (u+\frac{v-u}{2})\oplus \frac{v-u}{2}=u (u+2v−u)⊕2v−u=u 时就只要两个数了,其实也就是 u u u 和 v − u 2 \frac{v-u}{2} 2v−u 不存在在同一个位置为 1 1 1.
代码
#include <bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
long long u,v;
int main()//代码没什么好说的
{
scanf("%lld%lld",&u,&v);
if(u>v||(v-u)&1)
{
return 0&printf("-1\n");
}
if(!u)
{
if(!v)
{
return 0&printf("%lld\n",u);
}
return 0&printf("2\n%lld %lld\n",v/2,v/2);
}
if(u==v)
{
return 0&printf("1\n%lld",u);
}
if(u&((v-u)/2))
{
return 0&printf("3\n%lld %lld %lld",u,(v-u)/2,(v-u)/2);
}
return 0&printf("2\n%lld %lld",u+(v-u)/2,(v-u)/2);
}