• [hdu5270]按位统计,容斥,归并


    题意:给两个序列[a, a + n), [b, b + n),求所有数(ai + bj)的异或和,i,j∈[0,n)。

    思路:这个题思路比较巧妙,不难但是难想到。BC上的题解讲得非常清楚了,我就直接copy过来了吧

    我们考虑两个数AB。
    为了描述方便,我们设[P]的值为:当表达式P的值为真时,[P]=1,否则[P]=0
    我们现在考虑计算[(A+B)and(2i)>0]
    首先我们将A,B都对2i+1取模,显然这样是不会影响答案的
    则有一个十分显然的等式:
    [(A+B)and(2i)>0]=[(A+B)(2i)][(A+B)(2i+1)]+[(A+B)(32i)]
    这个式子相当容易理解,这里不多述了
    考虑每一位对答案的贡献是独立的,我们每一位分开做
    于是现在问题变成了:给定数组A,B,求满足Ai+Bjlimit的数对个数
    我们可以将A,B排序后,直接O(n)计算即可
    然而排序是O(nlogn)的,这样总复杂度就是O(nlognlogA)了,无法通过此题
    于是这里有个小技巧
    我们从高位往低位做,现在我们要实现的是:将A中每个数对P取模后将A排序
    我们发现A会被分成两段,一段小于P,一段大于等于P,只有后面一段要取模,我们可以取模后直接将这两段归并,复杂度是O(n)的
    时间复杂度:O(nlogA+nlogn)

     下面的代码就是根据题解写的,个人感觉也非常清晰了:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #pragma comment(linker, "/STACK:10240000,10240000")
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <algorithm>
    #include <queue>
    using namespace std;
     
    const int maxn = 1e5 + 7;
     
    int n;
    long long a[maxn], b[maxn];
     
    void sort(long long *a, long long md) {
        int pos = n;
        for (int i = 0; i < n; i ++) {
            if (pos == n && a[i] >= md) pos = i;
            a[i] = a[i] & (md - 1);
        }
        inplace_merge(a, a + pos, a + n);
    }
     
    bool solve(long long limit) {
        long long ans = 0;
        int that = n - 1;
        for (int i = 0; i < n; i ++) {
            while (that >= 0 && a[i] + b[that] >= limit) that --;
            ans += n - 1 - that;
        }
        return ans & 1;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
    #endif // ONLINE_JUDGE
        int T, cas = 0;
        cin >> T;
        while (T --) {
            cin >> n;
            for (int i = 0; i < n; i ++) {
                scanf("%I64d", a + i);
            }
            for (int i = 0; i < n; i ++) {
                scanf("%I64d", b + i);
            }
            sort(a, a + n);
            sort(b, b + n);
            long long ans = 0;
            for (int i = 61; i >= 0; i --) {
                sort(a, (long long)2 << i);
                sort(b, (long long)2 << i);
                long long res =
                    solve((long long)1 << i) ^
                    solve((long long)2 << i) ^
                    solve((long long)3 << i);
                ans |= res << i;
            }
            printf("Case #%d: %I64d ", ++ cas, ans);
        }
        return 0;
    }
  • 相关阅读:
    Link标签的media属性
    Moss2007ctx问题
    Moss2007 ListTemplate
    Html body的滚动条禁止与启用
    DOM的事件冒泡
    IE解析UL和LI的规则和问题
    AT&T汇编语言语法(一)(转)
    Linux 汇编语言开发指南 (转)
    Python 模块 jwt
    Excel2003和excel2007读取方法
  • 原文地址:https://www.cnblogs.com/jklongint/p/4576232.html
Copyright © 2020-2023  润新知