如 果 觉 得 下 面 难 以 理 解 , 可 以 去 这 里 看 一 种 较 为 简 单 的 解 法 如果觉得下面难以理解,可以去这里看一种较为简单的解法 如果觉得下面难以理解,可以去这里看一种较为简单的解法:saf
这 个 题 嘛 , 首 先 要 明 确 异 或 的 性 质 : 相 同 为 0 , 不 同 为 1. 这个题嘛,首先要明确异或的性质:相同为0,不同为1. 这个题嘛,首先要明确异或的性质:相同为0,不同为1.
举 个 例 子 , 我 们 来 构 造 u = 15 和 v = 127 的 情 况 举个例子,我们来构造u=15和v=127的情况 举个例子,我们来构造u=15和v=127的情况
注
意
到
,
异
或
是
二
进
制
,
我
们
把
15
的
二
进
制
写
下
来
注意到,异或是二进制,我们把15的二进制写下来
注意到,异或是二进制,我们把15的二进制写下来
1111
1111
1111
说
明
什
么
?
说
明
至
少
二
进
制
的
1
,
2
,
3
,
4
位
数
字
出
现
了
奇
数
次
,
二
进
制
的
其
他
位
出
现
了
偶
数
次
。
\color{Red}{说明什么?说明至少二进制的1,2,3,4位数字出现了奇数次,二进制的其他位出现了偶数次。}
说明什么?说明至少二进制的1,2,3,4位数字出现了奇数次,二进制的其他位出现了偶数次。
你 问 我 为 什 么 ? 请 看 异 或 的 定 义 , 假 如 出 现 偶 数 次 1 相 异 或 , 仍 然 为 0. 你问我为什么?请看异或的定义,假如出现偶数次1相异或,仍然为0. 你问我为什么?请看异或的定义,假如出现偶数次1相异或,仍然为0.
那 么 我 们 可 以 构 造 出 最 终 数 列 中 , 二 进 制 的 某 一 位 出 现 过 多 少 次 1. 那么我们可以构造出最终数列中,二进制的某一位出现过多少次1. 那么我们可以构造出最终数列中,二进制的某一位出现过多少次1.
基 于 贪 心 的 思 想 , 我 们 从 二 进 制 的 62 位 开 始 构 造 。 用 当 前 的 v 整 除 2 i 基于贪心的思想,我们从二进制的62位开始构造。用当前的v整除{2^i} 基于贪心的思想,我们从二进制的62位开始构造。用当前的v整除2i
如 果 在 15 中 出 现 过 这 一 位 , 说 明 我 们 想 构 造 奇 数 次 , 假 如 除 数 是 偶 数 就 − 1 如果在15中出现过这一位,说明我们想构造奇数次,假如除数是偶数就-1 如果在15中出现过这一位,说明我们想构造奇数次,假如除数是偶数就−1
如 果 在 15 没 出 现 过 , 说 明 我 们 想 构 造 偶 数 次 , 假 如 是 奇 数 就 − 1 如果在15没出现过,说明我们想构造偶数次,假如是奇数就-1 如果在15没出现过,说明我们想构造偶数次,假如是奇数就−1
然 后 每 一 次 都 v 都 减 去 构 造 的 数 字 然后每一次都v都减去构造的数字 然后每一次都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]<<" ";
}