Codeforces 734F Anton and School

题目:http://codeforces.com/problemset/problem/734/F

F. Anton and School
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Anton goes to school, his favorite lessons are arraystudying. He usually solves all the tasks pretty fast, but this time the teacher gave him a complicated one: given two arrays b and c of length n, find array a, such that:

where a and b means bitwise AND, while a or b means bitwise OR.

Usually Anton is good in arraystudying, but this problem is too hard, so Anton asks you to help.

Input

The first line of the input contains a single integers n (1 ≤ n ≤ 200 000) — the size of arrays b and c.

The second line contains n integers bi (0 ≤ bi ≤ 109) — elements of the array b.

Third line contains n integers ci (0 ≤ ci ≤ 109) — elements of the array c.

Output

If there is no solution, print  - 1.

Otherwise, the only line of the output should contain n non-negative integers ai — elements of the array a. If there are multiple possible solutions, you may print any of them.

Examples
input
Copy
4
6 8 4 4
16 22 10 10
output
3 5 1 1 
input
Copy
5
8 25 14 7 16
19 6 9 4 25
output
-1

 

解析

这是一道乱搞思路题。

感谢jhy大佬的推荐顺便宣传一下他的博客http://www.cnblogs.com/JYYHH/

 

好了步入正题:

考虑两个数b,c,把他们拆成二进制一位一位看。

a&b 在第k为为1的条件是a和b的第k位都为1

a|b   则是在第k为有一个为1即可。

为什么我们要分析这个呢?

因为也没有什么可以乱搞的了

我们来计算一下(a&b)+(a|b),

如果两个数(二进制)第k位都为1,那么

第k位的贡献就是2*(1<<k),(包含第0位)。

如果只有一个数为1,那么

贡献就是(1<<k),

否则贡献为0,

这样子得到的结果,是不是和a+b的结果一样?

好了经过乱搞我们得到了一个等式(a&b)+(a|b)==a+b

这个等式回头再用。

 

好了我们得到了这个等式是来乱搞转化的。

我们尝试去求a。

我们知道了:

b[i]=sigma(ai&aj) c[i]=sigma(ai|aj),

令f[i]=b[i]+c[i] ==> f[i]=n*a[i]+sigma(aj)。

我们把sigma(ai)消去:

sigma(f[i])=2n*sigma(aj)    sigma(aj)=sigma(f[i])/2n

然后我们带入原来推出来的:

得到:a[i]=(f[i]-sigma(f[i]/2n))/n。

 

注意:此时得到的ai不一定能满足原来的bi,ci的条件,

所以我们要用n^2的方法去检查一下是否满足条件

正常方法检查超时稳稳的。

我们还是只能——乱搞用位运算来转化。

由于我们已经知道了ai,可以尝试用ai去推出bi和ci的值。

先考虑b:

考虑bi的每一位,假设考虑第k位,

如果ai的第k位为1,那么对bi这个数的贡献就是:

在a中第k为为1的ai个数<<j。

好吧我们定义一下变量:

a[i][k]代表ai的第k位是什么数,g[x]代表第x位为1的ai的个数,

我们设cb[i][k]代表求出来的bi的第k位对bi总体的贡献。

那么我们易知:

b[i]=sigma(cb[i][k]<<k),

那么cb[i][k]和ai有关,我们可以找到关系:

cb[i][k]=0           a[i][k]==0

            g[k]        a[i][k]==1

好了对此我们就可以快速算出bi的值,跟原来的bi比较了。

ci的算法也同理,c[i][k]的算法请自行思考其实你们可以直接看代码的orz

好了蒟蒻的代码献上:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 const int maxn=200010;
 9 int n;
10 ll sum;
11 ll a[maxn],b[maxn],c[maxn];
12 ll f[maxn],g[maxn];
13 ll ca[maxn][35],cb[maxn],cc[maxn];
14 bool check(){
15     for (int i=1;i<=n;++i){
16         for (int j=0;j<=31;++j){
17             ca[i][j]=a[i]&(1<<j)?1:0;
18             g[j]+=ca[i][j];
19         }
20     }
21     for (int i=1;i<=n;++i){
22         for (int j=0;j<=31;++j){
23             ll ckb=ca[i][j]?g[j]:0;
24             ll ckc=ca[i][j]?n:g[j];
25             cb[i]+=ckb<<j; cc[i]+=ckc<<j;
26         }
27     }
28     for (int i=1;i<=n;++i){
29         if (cb[i]!=b[i]||cc[i]!=c[i]) return false;
30     }
31     return true;
32 }
33 int main(){
34     scanf("%d",&n);
35     for (int i=1;i<=n;++i){
36         scanf("%lld",&b[i]);
37     }
38     for (int i=1;i<=n;++i){
39         scanf("%lld",&c[i]);
40     }
41     for (int i=1;i<=n;++i){
42         f[i]=b[i]+c[i];
43         sum+=f[i];
44     }
45     sum/=2*n;
46     for (int i=1;i<=n;++i){
47         a[i]=(f[i]-sum)/n;
48     }
49     if (check()){
50         for (int i=1;i<=n;++i) 
51             printf("%lld ",a[i]);
52     }else{
53         printf("-1");
54     }
55     return 0;
56 }
View Code

 

posted @ 2018-03-02 22:33  lonlyn  阅读(247)  评论(0编辑  收藏  举报