zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    eclipse运行纯servlet程序
    VS中lib和dll
    eclipse部署web项目至本地的tomcat但在webapps中找不到
    【2018.07.28】(字符串/回文串)学习Manacher算法小记
    【2018.07.26】建立博客~
    【2018.07.27】(字符串/找相同)学习KMP算法小记
    [转]数据库范式那些事
    [转]Windows平台下的多线程编程
    mondrian schema学习(1)
    [转]SQL查询入门
  • 原文地址:https://www.cnblogs.com/gjc1124646822/p/8495306.html
Copyright © 2011-2022 走看看