D. Ehab the Xorcist(纯构造方法)

\(如果觉得下面难以理解,可以去这里看一种较为简单的解法\):saf

\(这个题嘛,首先要明确异或的性质:相同为0,不同为1.\)

\(举个例子,我们来构造u=15和v=127的情况\)

\(注意到,异或是二进制,我们把15的二进制写下来\)

\[1111
\]

\(\color{Red}{说明什么?说明至少二进制的1,2,3,4位数字出现了奇数次,二进制的其他位出现了偶数次。}\)

\(你问我为什么?请看异或的定义,假如出现偶数次1相异或,仍然为0.\)

\(那么我们可以构造出最终数列中,二进制的某一位出现过多少次1.\)

\(基于贪心的思想,我们从二进制的62位开始构造。用当前的v整除{2^i}\)

\(如果在15中出现过这一位,说明我们想构造奇数次,假如除数是偶数就-1\)

\(如果在15没出现过,说明我们想构造偶数次,假如是奇数就-1\)

\(然后每一次都v都减去构造的数字\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll u,v,a[64],vis[64],ans[109],num[109],cnt,xu;
bool work()
{
    ll minn=1e18,shu=0;
    for(int i=1;i<=62;i++)
        if(vis[i])
        minn=min(minn,vis[i]);//找出出现次数最少的 
    if(minn==1e18)  return false;//已经可以输出了 
    for(int i=1;i<=62;i++)
    {
        if(vis[i]==0)   continue;
        vis[i]-=minn,shu+=a[i];//都加上去 
    }
    ans[++cnt]=shu,num[cnt]=minn,xu+=minn;
    return  true;
}
int main()
{
    a[1]=1;
    for(int i=2;i<=62;i++)   a[i]=a[i-1]*2;//二进制的额每一位代表的数 
    cin>>u>>v;
    for(int i=1;i<=62;i++)
    if(u&a[i])//标记是否在u出现过 
    {
        vis[i]=1;//出现过那么至少要有一次 
        v-=a[i];
    }
    if(v<0)  cout<<-1,exit(0);
    for(int i=62;i>=1;i--)
    {
        ll z=v/a[i];
        if(z==0)    continue;
        if(z%2==1&&vis[i])  z--;//出现过应该构造奇数 
        if(z%2==1&&!vis[i]) z--;//没出现过应该构造偶数 
        vis[i]+=z;
        v-=a[i]*z;
    }
    if(v!=0)    cout<<-1,exit(0);
    while(work())   continue;//贪心构成数字 
    cout<<xu<<endl;
    for(int i=1;i<=cnt;i++)
    for(int j=1;j<=num[i];j++)
        cout<<ans[i]<<" ";
}

原文链接: https://www.cnblogs.com/iss-ue/p/12809583.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    D. Ehab the Xorcist(纯构造方法)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/345449

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午3:15
下一篇 2023年3月2日 上午3:15

相关推荐