第一次补完CF题。
首先看到b[i] = a[i] & a[1] + a[i] & a[2] + ... + a[i] & a[n], c[i] = a[i] | a[1] + a[i] | a[2] + ... + a[i] | a[n]。 联想到a[i] + a[j] = a[i] | a[j] + a[i] & a[j]。
因此b[i] + c[i] = n * a[i] + sum。推出这个以后的就比较好求了。注意最后要判断求出的a数组是否能还原到b和c数组,这个有一个小细节。具体见代码:
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 200005;
long long a[maxn];
long long b[maxn], c[maxn];
long long cnt[60];
int main()
{
int n;
scanf("%d", &n);
long long sum = 0;
for(int i = 0; i < n; ++i)
{
scanf("%I64d", &b[i]);
sum += b[i];
}
for(int i = 0; i < n; ++i)
{
scanf("%I64d", &c[i]);
sum += c[i];
}
if(sum % (2 * n) != 0)
{
printf("-1\n");
return 0;
}
sum = sum / 2 / n;
for(int i = 0; i < n; ++i)
{
if((-sum + b[i] + c[i]) < 0 || (-sum + b[i] + c[i]) % n != 0)
{
printf("-1\n");
return 0;
}
a[i] = (-sum + b[i] + c[i]) / n;
}
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < 60; ++j)
if(a[i] >> j & 1)
{
++cnt[j];
}
}
for(int i = 0; i < n; ++i)
{
long long tb = 0, tc = 0;
for(int j = 0; j < 60; ++j)
if(a[i] >> j & 1)
{
tb += cnt[j] * (1LL << j);
tc += n * (1LL << j);
}
else
tc += cnt[j] * (1LL << j);
if(tc != c[i] || tb != b[i])
{
printf("-1\n");
return 0;
}
}
for(int i = 0; i < n; ++i)
{
if(i)
printf(" ");
printf("%I64d", a[i]);
}
}