D. Ehab the Xorcist

传送门:https://codeforces.ml/contest/1325/problem/D

题意:给你两个整数u和v,需要你构造一个最短的序列,使他们的异或和是u,和是v,输出序列长度和序列的每个数,若构造不出来输出-1。

思路:当u>v的时候显然没有解,因为u对应的二进制位已经比v大了。

   当u==v时,输出一个u就行。

   那么当u<v时就是我们要讨论的情况了,对于最一般的情况,我们令x=(v-u)/2,我们可以构造出u,x,x这个序列一定符合题意,所以最长长度为三,但有一种特殊情况,就是a^b==u,a+b==v,我们知道异或就是不进位加法,而a+b也可以写成a^b+2(a&b),也就是加法=不进位加法+进位数字,带入我们参数我们就可以得到a&b=(v-u)/2,惊不惊喜意不意外,我们设为x,我们看x的二进制位,若x二进制位上有1,则a和b该位上一定是1,那么他们的异或u该位就是0,x二进制上为0时没有限制。所以我们可以得出,当x位上有1,但u上也是1->(x&u!=0)则不满足此特殊情况,可以输出一般情况的解了。当满足的时候,代表x&u==0,也就是x^u==x+u,所以我们可以构造出u+x,x这个序列,长度为2且符合题意!

 

ac代码:

#include<iostream>
using namespace std;
typedef long long ll;
ll u,v;
int main()
{
    cin>>u>>v;
    if(u>v) return cout<<-1,0;
    if(u==0&&v==0)
        return cout<<0,0;
    if(u==v)
        return cout<<1<<'\n'<<u,0;
    ll x=(v-u)/2;
    if((v-u)&1) return cout<<-1,0;
    if((x&u)==0){
        cout<<2<<'\n'<<u+x<<" "<<x;
        return 0;
    }
    cout<<3<<'\n';
    cout<<u<<" "<<x<<" "<<x;
    return 0;
}

 

posted @ 2020-03-15 15:00  艾尔夏尔-Layton  阅读(503)  评论(1编辑  收藏  举报