题解 CF1325D 【Ehab the Xorcist】
Forever_Pursuit
2020-03-15 13:33:18
提供一种与大多数题解不同的方法。
显然 $u>v$ 或 $u$ 与 $v$ 奇偶性不同时无解。
对于有解的情况,以 $u=14$ ,$v=20$ 为例,
先把 $u$ 和 $v$ 变成长度相同的 $2$ 进制串,高位补 $0$ 。
$$u:01110\ \ \ \ \ v:00101$$
接着把答案数组看成 $2$ 进制,把 $v$ 的每一位转化成答案数组中这一位为 $1$ 的数的数量。
忽略其他数,对某一位上的数进行考虑。
若想让 $u$ 的某一位为 $0$ ,则 $v$ 的这一位显然要是偶数;
若想让 $u$ 的某一位为 $1$ ,则 $v$ 的这一位显然要是奇数。
即 $u$ 与 $v$ 的每一位的奇偶性必须相同。
然后从最高位开始循环,若第 $i$ 位 $u$ 与 $v$ 奇偶性不同,则 $v_i--$ ,$v_{i-1}+=2$ ,显然这样不影响 $v$ 的大小。
对以上例子进行这步操作后 $:$
$$u:01110\ \ \ \ \ v:00101$$
$$↓$$
$$u:01110\ \ \ \ \ v:00120$$
$$↓$$
$$u:01110\ \ \ \ \ v:00310$$
$$↓$$
$$u:01110\ \ \ \ \ v:2\text-1310$$
然后发现出现了负数,于是需要让低位向高位借位,类似于减法借位。
这一步从低位开始循环。
若 $v$ 的第 $i$ 位为负数则 $v_i+=2$ ,$v_{i+1}--$ 。
但是这样会改变高位的奇偶性,所以仍需要在第 $i$ 位 $u$ 与 $v$ 奇偶性不同时 $v_i--$ ,$v_{i-1}+=2$ 。
对以上例子进行这步操作后 $:$
$$u:01110\ \ \ \ \ v:2\text-1310$$
$$↓$$
$$u:01110\ \ \ \ \ v:21210$$
$$↓$$
$$u:01110\ \ \ \ \ v:23110$$
此时保证了 $u$ 与 $v$ 的每一位奇偶性相同且没有负数。
答案数组的第 $i$ 位为 $1$ 的次数是 $v_i$ ,所以答案数组的最小长度即为 $v$ 数字串中最大的数,在以上例子中答案数组的最小长度为 $3$ 。
构造答案数组十分简单,只要满足在 $2$ 进制下答案数组第 $i$ 位为 $1$ 的数的数量等于 $v_i$ 即可。
对于以上例子,答案数组可构造为:
$$ans_1:11110$$
$$ans_2:11000$$
$$ans_3:01000$$
每一位相加就是:
$$23110\text{(即为v数字串)}$$
最后转化为 $10$ 进制输出即可。
```cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 64
int n,m,a[N],b[N];
signed main(){
scanf("%lld%lld",&n,&m);
if(n>m||((m-n)&1)){
puts("-1");
return 0;
}
int tot1=0,tot2=0,tot,ans=0,t;
a[++tot1]=n&1;
while(n/=2)
a[++tot1]=n&1;
b[++tot2]=m&1;
while(m/=2)
b[++tot2]=m&1;
tot=max(tot1,tot2);
for(int i=tot;i>0;i--)
if((b[i]-a[i])&1)b[i-1]+=2,b[i]--;
for(int i=1;i<tot;i++){
if((b[i]-a[i])&1)b[i-1]+=2,b[i]--;
if(b[i]<0)b[i]+=2,b[i+1]--;
}
for(int i=1;i<=tot;i++)
ans=max(ans,b[i]);
printf("%lld\n",ans);
for(int i=1;i<=ans;i++){
t=0;
for(int j=1,k=1;j<=tot;j++,k<<=1)
if(b[j])t+=k,b[j]--;
printf("%lld ",t);
}
return 0;
}
```