CF1325D Ehab the Xorcist
传送门
题意:让你构造最短的一个数组,满足所有元素的异或和为\(u\),和为\(v\).
这题典型的cf题,思维难度挺大,然后代码量挺少。
这题应该是充分地锻炼了我的位运算本领吧。
首先要观察到这么个性质,就是\(u\)和\(v\)必须奇偶相同(显然,二进制最低位1的奇偶性相同),那么如果\(u > v\),或\(u,v\)奇偶性不同,都输出-1.
除以上情况外,令\(x=\frac{v-u}{2}\),那么序列\(\{u,x,x\}\)必定是符合要求的(好妙啊,我咋就没想出来)。因此我们只要判断是否能由两个数构造出来,即\(\exist a, b, \textrm{s.t.} a \bigoplus b = u, a + b = v\).
考虑到异或实际上就是不进位的加法,而利用按位与操作,我们能知道哪些位会进位,那么就有\(a+b=a \bigoplus b + 2 * a \textrm{&} b\),因此\(a \& b = \frac{a + b - a \bigoplus b}{2}=\frac{v-u}{2}=x\)(神奇吧)
那么什么时候存在这样的\(a,b\)呢?有上面推论可知,\(a\& b=x, a \bigoplus b = u\),那么当\(x\)某一位为1时,\(u\)这一位必须是0;而当\(x\)某一位为0时,\(u\)这一位随意。所以当\(x \& u = 0\)时,\(a,b\)存在;否则答案只能是\(\{u,x,x\}\)。
那\(a,b\)如何构造?会发现,当\(x \& u=0\)时,\(x+u=x \bigoplus u\),因此构造\(\{x+u,x\}\)就行了!
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<queue>
#include<assert.h>
#include<ctime>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
#define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
//const int maxn = ;
In ll read()
{
ll ans = 0;
char ch = getchar(), las = ' ';
while(!isdigit(ch)) las = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(las == '-') ans = -ans;
return ans;
}
In void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif
}
int main()
{
// MYFILE();
ll u = read(), v = read();
if(u > v || (u & 1) != (v & 1)) puts("-1");
else if(u == v)
{
if(u) printf("1\n%lld\n", u);
else puts("0");
}
else
{
ll x = (v - u) >> 1;
if(x & u) printf("3\n%lld %lld %lld\n", u, x, x);
else printf("2\n%lld %lld\n", u + x, x);
}
return 0;
}