【题目链接】传送门
【题意】
给出u,v,请找到一组数,使得 异或和=u,和=v。若不存在输出“-1”,如果有多组,输出最短的一组。
【题解】
一开始我仅仅留意如何构造,没有留意题意中的最短。不过误打误撞发现一点规律。
我们取最极端的例子就是u=v,我们可以把2进制下所有的位进行相加。
u>v,必定是不存在。
u<v,两者之间的差值,d=v-u。构造他们Xor=u,Sum=v,我们可以弄出来m = d / 2 ,
u = u ^ m ^ m , v = u + m + m
a)根据这个条件,如果d为奇数必定不存在。(根据构造出来的条件)
b)反面证明,如果d为奇数。我们考虑最小的位(bit)
u^d_bit(0) != u_bit(0) ,我们对于d和u无论如果拆分,最低位都是不一致(即u为奇数,v为偶数,或者相反,反正最低位不一致)。
通过a)和b)两种情况枚举后发现,u<v,有意义的一组仅有,d 为偶数时。
u = v 时,答案就是“1 u”
u < v 时,d =v-u为偶数时。m=d/2
答案最长就是“3 u m m”,同时可能有u&m==0,此时答案就是“2 u^m m”
【具体代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 using namespace std; 5 typedef long long ll; 6 const int N = 100; 7 vector<ll> Ans; 8 int main() 9 { 10 ll u , v ; 11 scanf("%lld%lld",&u,&v); 12 if( u == v && v == 0 ){ 13 printf("0 "); 14 }else if( u > v || ((v - u) & 1 )){ 15 printf("-1 "); 16 }else if( u == v ){ 17 printf("1 %lld ",u); 18 }else{ 19 ll t = ( v - u ) / 2 ; 20 if( (u & t) == 0 ){ 21 printf("2 %lld %lld ",t,u^t); 22 }else{ 23 printf("3 %lld %lld %lld ",u,t,t); 24 } 25 } 26 return 0 ; 27 }