• 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
  • 相关阅读:
    常用颜色代码 (30种)
    C++ 调用lib 和 dll的 方法 及 动态库DLL与静态库lib的区别
    如何: 通过HTML文档对象模型访问文档中的ActiveX控件的属性 .
    理解预编译头
    #ifndef用法总结 .
    C++中MessageBox()的详细用法
    如何用Javascript捕获ActiveX对象的事件
    ActiveX控件调用JavaScript函数的方法
    MFC Activex与JavaScript的接口交互
    include包含文件查找的顺序 .
  • 原文地址:https://www.cnblogs.com/gjc1124646822/p/8495306.html
Copyright © 2020-2023  润新知