题目大意:
给定两个正整数序列(b,c)构造一个正整数序列(a)使其满足
[left{
egin{array}{}
b_i=(a_i ext{ and }a_1)+(a_i ext{ and }a_2)+...+(a_i ext{ and }a_n) \
c_i = (a_i ext{ or }a_1)+(a_i ext{ or }a_2)+...+(a_i ext{ or }a_n)
end{array}
ight.
]
题解:
我们有这么一个性质((a_i ext{ and } b_i)+(a_i ext{ or }b_i)= a+b)
所以我们把所有的(b_i,c_i)加和,得到
[left{
egin{array}{}
b_1+c_1 = na_1 + sum{a_i} \
b_2+c_2 = na_2 + sum{a_i} \
... \
b_n+c_n = na_n + sum{a_i}
end{array}
ight.
]
然后再把所有的式子加和得到
(sum{a_i} = frac{sum{b_i} + sum{c_i}}{2n})
然后我们可以利用这个解出所有的(a_i)
我也不知道为什么必须对每一位都特殊判定,不过不判定的话下面这组数据过不去
1
3
5
应该是不可行,但是如果不进行数位判定的话会输出4...
哪位大神可以来救救我。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 200010;
ll b[maxn],c[maxn],a[maxn];
int cnt[32][2];
int main(){
int n;read(n);
ll sum = 0;
for(int i=1;i<=n;++i) read(b[i]),sum += b[i];
for(int i=1;i<=n;++i) read(c[i]),sum += c[i];
if(sum % (n<<1) != 0) return puts("-1");
sum /= (n<<1);
for(int i=1;i<=n;++i){
ll x = b[i] + c[i] - sum;
if(x < 0 || (x%n != 0)) return puts("-1");
a[i] = x/n;
for(int j=0;j<31;++j) ++cnt[j][(a[i]>>j)&1];
}
for(int i=1;i<=n;++i){
for(int j=0;j<31;++j) b[i] -= ((a[i]>>j)&1)*cnt[j][1]<<j;
if(b[i] != 0) return puts("-1");
}
for(int i=1;i<=n;++i){
printf("%I64d",a[i]);
if(i != n) putchar(' ');
else putchar('
');
}
getchar();getchar();
return 0;
}