https://codeforces.com/problemset/problem/1325/D
思路:
异或的性质:相同为0,不同为1.
先把u这个数字转化成二进制形式发现有的是1,有的是0.那么1的那一位接下来如果这一位还要有1,那么只能是奇数,如果是0,那么只能是偶数。
于是开始先把v减去需要构造的u的至少大小,减完如果是<0那么就说明不可能构造成功。
不然就从高位开始,看是否整除当前位,整除的话看当前位是1还是0.。1的话次数要改成奇数。0的话次数要改成偶数。
统计完之后如果v!=0,那么也无解。
最后我们重复每次在能有1的时候取个1合成一个数出来,直到剩余的所有位数都是0了。
特判u==v的情况和u==0&&v==0的情况。
另外自己一个转存数组的错误:如果要转存,一定要看原来的数组前面是否有逻辑上的break或者continue,不然会产生转存不完全的问题。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=123;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn],ans[maxn],tot=0;
LL num[maxn];
LL vis[maxn];
LL b[maxn];
LL total=0;
bool solve(){
LL minv=1e18;
LL shu=0;
for(LL i=0;i<=62;i++){
if(b[i]) minv=min(minv,b[i]);
}
if(minv==1e18) return false;
minv=min(minv,(LL)1);
for(LL i=0;i<=62;i++){
if(b[i]==0) continue;
b[i]-=minv;
shu+=a[i];
}
ans[++tot]=shu;
return true;
}
///大数时((LL)1<<32),这个1也要LL
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL u,v;cin>>u>>v;
if(u==v&&u!=0){
cout<<1<<"\n"<<u<<"\n";
return 0;
}
a[0]=1;
for(LL i=1;i<=62;i++) a[i]=a[i-1]*2;
for(LL i=62;i>=0;i--){
if(a[i]&u) vis[i]=1,v-=a[i];
}
///debug(v);
if(v<0){cout<<"-1"<<"\n";return 0;}
for(LL i=62;i>=0;i--){
LL temp=v/a[i];
b[i]=vis[i];
if(temp==0) continue;
if(vis[i]){
if(temp%2==1) temp--;
}
else if(!vis[i]){
if(temp%2==1) temp--;
}
b[i]+=temp;
vis[i]+=temp;
v-=temp*a[i];
}
if(v!=0){
cout<<"-1"<<"\n";return 0;
}
while( solve()==1) continue;
cout<<tot<<"\n";
for(LL i=1;i<=tot;i++){
cout<<ans[i]<<" ";
}
cout<<"\n";
return 0;
}