题目大意:
有
a,b,c
三个长度为
n(n≤2∗105)
的数列,其中
bi=∑njaiandaj
ci=∑njaioraj
求原数组a
题解:
如果知道
a+b=aandb+aorb
,这个问题就好解决了。
bi+ci=n∗ai+∑njaj
sum=∑niai
∑nibi+ci=n∗∑niai+n∗∑njaj=2n∗∑niai=2n∗sum
ai=bi+ci−sumn
最后只要验证一下a是否能满足b和c即可,按位预处理。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200021;
typedef long long ll;
int b[maxn],c[maxn],a[maxn];
int num[34];
int main(){
int n;
scanf("%d",&n);
for(int i = 0;i < n;i++) scanf("%d",&b[i]);
for(int i = 0;i < n;i++) scanf("%d",&c[i]);
ll sum = 0;
memset(num,0,sizeof(num));
for(int i = 0;i < n;i++){
sum += b[i]+c[i];
}
if(sum%n||sum%2){
printf("-1\n");
return 0;
}
int flag = 1;
sum /= 2*n;
for(int i = 0;i < n;i++){
int tmp = b[i]+c[i]-sum;
if(tmp%n){
flag = 0;
break;
}
a[i] = tmp/n;
}
for(int i = 0;i < n;i++)
for(int j = 0;j < 32;j++)
if((a[i]>>j)&1) num[j]++;
for(int i = 0;i < n;i++){
int sb,sc;
sb = sc = 0;
for(int j = 0;j < 32;j++){
if((a[i]>>j)&1){
sb += num[j]*(1<<j);
sc += n*(1<<j);
}
else{
sc += num[j]*(1<<j);
}
}
if(sb != b[i]||sc != c[i]){
flag = 0;
break;
}
}
if(flag){
for(int i=0;i< n;i++){
printf("%d",a[i]);
if(i == n-1) printf("\n");
else printf(" ");
}
}
else{
printf("-1\n");
}
return 0;
}