codeforces 1325D 位运算+思维

ok

 

 

 

 题意:给了两个数u,v(1e18),输出一个长度为n的数组,使得该数组异或等于u,相加等于v。

思路: 当v大于u的时候无结果,v=u的时候分情况,如果u=0,输出0,否则输出1和u。

  根据异或的规律,我们可以先让u和0异或成为u,则满足了第一个条件,如果还想满足第二个条件,则要根据v-u的值来处理。把v-u平均分在u和0的二进制同时为0的位置上,即使得u+a 等于0+a,使得(u+a)^(0+a)等于u,且u+a+0+a即u+2a为v,但是v-u不一定能为偶数,如果为奇数,经验证,是不可能有解的,所以v-u为奇数的时候输出-1。

如何把(v-u)/2 = a平均分到u和0上使得(u+a)^(0+a)等于u呢,u的二进制有1有0,0的二进制只有0,只需要把a的二进制求出来,如果a的二进制和u的二进制没有存在同一位置都为1的情况(如果都为1,异或为0,但是0的二进制为0,加上了a则为1,加上了之后(u+a)^(0+a)遍不再等于u了),直接输出2,a,v-a。如果存在都为1,则输出3,u,a,a即为最优解。

 

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector>
    //const int maxn = 1e5+5;
    #define ll long long
    #define inf  0x3f3f3f3f
    #define FOR(i,a,b) for( int i = a;i <= b;++i)
    #define bug cout<<"--------------"<<endl
     
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

    using namespace std;
    int a[1000000],b[1000000];
    int main()
    {
        ll u,v;
        cin>>u>>v;
        ll tmp = (v - u)/2;
        int t1 = 0,t2 = 0;

        ll temp = u;

        while(temp)
        {
            a[++t1] = temp%2;
            temp /= 2;
        }
    /*    for(int i = 1;i <= t1; ++i)
        {
            cout<<a[i]<<" ";
        }*/
        if((v-u) % 2 == 1 || (v-u) < 0)
        {
            cout<<-1<<endl;
        }
        else if(v-u == 0)
        {
            if(u == 0)
                cout<<0<<endl;
            else 
            {
                cout<<1<<endl;
                cout<<u<<endl;
            }
            
        }
        else 
        {
            ll hhh = tmp;
            while(hhh)
            {
                b[++t2] = hhh%2;
                hhh /= 2;
            }
            int flag = 0;
            for(int i = 1;i <= t1; ++i)
            {
                if(a[i] == b[i] && a[i] == 1)
                {
                    flag = 1;
                    break;
                }
            }
            if(flag == 0)
            {
    /*            ll ans = 1;
                ll maxx = max(t1,t2);
                for(int i = maxx;i >= 1; --i)
                {
                    b[i] += a[i];
                    if(b[i] == 0)
                    {
                        ans *= 2;
                    }
                    else if(b[i] == 1)
                    {
                        ans = ans * 2 + 1;
                    }
                }*/
                ll ans = v-tmp;
                cout<<2<<endl;
                cout<<ans<<" "<<tmp<<endl;
            }
            else if(flag == 1)
            {
                cout<<3<<endl;
                cout<<u<<" "<<tmp<<" "<<tmp<<endl;
            }
        }

    }

 

posted @ 2020-05-10 19:05  阿斯水生产线  阅读(210)  评论(0编辑  收藏  举报