zoukankan      html  css  js  c++  java
  • Codeforces Round #379 (Div. 2) F. Anton and School

    题意:
    给你n对 b[i], c[i], 让你求a[i],不存在输出-1
    b[i] = (a[i] and a[1]) + (a[i] and a[2]) + (a[i] and a[3]) +...+ (a[i] and a[n]);
    c[i] = (a[i] or a[1]) + (a[i] or a[2]) + (a[i] or a[3]) +...+ (a[i] or a[n]);
    and 和 or 是按位与 或

    思路:
    (a and b) + (a or b) = (a + b) 证明显然
    所以把每个b[i]+c[i] = n*a[i] + s, s为所有a的和
    这样 就可以解出每个 a[i]了,且解唯一,证明比较显然

    但是,解出的解不一定就是正确解!
    为什么会这样呢?
    因为解方程的时候 把b[i] c[i]看成了一个整体。
    也就是他们的和是满足的,但是他们自身可能不满足。
    举个例子:n = 1, b[0] = 3, c[0] = 5;
    发现用上面的方法是有解的 a[0] = 4, 但是很显然,这个也并不合法

    所有我们需要检测每一个b,c是否合法。
    n那么大,暴力n方肯定是不行了。
    我们要这样操作:
    用A[i][j]表示 a[i]的第j位是否为1,顺便求出k[j],k[j]表示所有a中的第j位有多少个1 处理的时间复杂度O(n*logv)
    再求出B[i][j], C[i][j]
    B[i][j] = (A[1][j] and A[i][j]) + (A[2][j] and A[i][j]) + ... + (A[n][j] and A[i][j]);
    C[i][j] = (A[1][j] or A[i][j]) + (A[2][j] or A[i][j]) + ... + (A[n][j] or A[i][j]);
    这个不用暴力求,因为我们刚刚已经求出了k[j]
    显然地,有下面的式子:
    if A[i][j] = 0: B[i][j] = 0, C[i][j] = k[j]
    else B[i][j] = k[j], C[i][j] = n

    有了B C后我们就能很快的求出b, c了
    b[i] = B[i][0]*2^0 + B[i][1]*2^1 + ...
    c[i] = C[i][0]*2^0 + C[i][1]*2^1 + ...

    最终的时间复杂度O(n*logv), v=max(a1,a2,..,an)

    具体代码如下:

     1 const int maxn = 200000 + 10;
     2 LL b[maxn], c[maxn], a[maxn];
     3 LL A[maxn][35], B[maxn][35], C[maxn][35], k[maxn];
     4 LL s;
     5 int n;
     6 
     7 void init()
     8 {
     9     scanf("%d", &n);
    10     for (int i = 0; i < n; i ++) scanf("%lld", b + i);
    11     for (int i = 0; i < n; i ++) scanf("%lld", c + i);
    12 }
    13 
    14 bool check() //返回求出的答案是否合法
    15 {
    16     for (int j = 0; j < 31; j++)
    17     {
    18         for (int i = 0; i < n; i++)
    19         {
    20             A[i][j] = a[i] & (1ll << j) ? 1 : 0;
    21             k[j] += A[i][j];
    22         }
    23     }
    24     for (int j = 0; j < 31; j++)
    25     {
    26         for (int i = 0; i < n; i++)
    27         {
    28             if (A[i][j])
    29             {
    30                 B[i][j] = k[j];
    31                 C[i][j] = n;
    32             }
    33             else
    34             {
    35                    B[i][j] = 0;
    36                 C[i][j] = k[j];
    37             }
    38         }
    39     }
    40 
    41     for (int i = 0; i < n; i++)
    42     {
    43         LL sumB = 0, sumC = 0;
    44         for (int j = 0; j < 31; j++)
    45         {
    46             sumB += B[i][j] * (1ll << j);
    47             sumC += C[i][j] * (1ll << j);
    48         }
    49         if (sumB != b[i] || sumC != c[i]) return false;
    50     }
    51     return true;
    52 }
    53 
    54 void solve()
    55 {
    56     bool ans = true;
    57     for (int i = 0; i < n; i++)
    58     {
    59         s += b[i] + c[i];
    60     }
    61     if (s % (2 * n)) ans = false;
    62     s /= 2 * n;
    63     for (int i = 0; i < n; i++)
    64     {
    65         a[i] = (b[i] + c[i] - s) / n;
    66         if ((b[i] + c[i] - s) % n) ans = false;
    67     }
    68     if (!ans || !check()) printf("-1
    ");
    69     else
    70     {
    71         for (int i = 0; i < n;i ++)
    72         {
    73             printf("%lld ", a[i]);
    74         }
    75     }
    76 }
    77 
    78 int main()
    79 {
    80     init();
    81     solve();
    82     return 0;
    83 }
  • 相关阅读:
    Python算法:推导、递归和规约
    K-means的缺点(优化不仅仅是最小化误差)
    从统计学角度来看深度学习(2):自动编码器和自由能
    从统计学角度来看深度学习(1):递归广义线性模型
    Why are Eight Bits Enough for Deep Neural Networks?
    VCS引起的oracle数据库异常重新启动一例
    赵雅智:service_startService生命周期
    第九章 两种模式的比較
    CSDN Markdown简明教程3-表格和公式
    OpenStack_Swift源代码分析——Object-auditor源代码分析(1)
  • 原文地址:https://www.cnblogs.com/liangyongrui/p/6076448.html
Copyright © 2011-2022 走看看