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

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

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

我们考虑两个数A,B。
为了描述方便,我们设[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)≥(3∗2i)]
这个式子相当容易理解,这里不多述了
考虑每一位对答案的贡献是独立的,我们每一位分开做
于是现在问题变成了:给定数组A,B,求满足Ai+Bj≥limit的数对个数
我们可以将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\n", ++ cas, ans);

    }

    return 0;

}

时间: 2024-10-20 09:25:52

[hdu5270]按位统计,容斥,归并的相关文章

zoj 3688 The Review Plan II 禁位排列 棋盘多项式 容斥

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4971 题意:共有N天和N个章节,每天完成一个章节,规定第i个章节不可以在第i天或者i+1天完成(第N个章节则是第N天和第1天不能),求分配能完成所有章节的方案数. 思路: 主要还是根据棋盘多项式的公式来求解: 但是这题和ZOJ3687不同,数据量N最大有100000,因此不能爆搜,需要推一下公式. 按照题意,先求禁位组成的棋盘的棋盘多项式,再用容斥.禁位组成的棋盘如

HDU5768Lucky7(中国剩余定理+容斥定理)(区间个数统计)

When ?? was born, seven crows flew in and stopped beside him. In its childhood, ?? had been unfortunately fall into the sea. While it was dying, seven dolphins arched its body and sent it back to the shore. It is said that ?? used to surrounded by 7

hdu6059 Kanade&#39;s trio 字典树+容斥

转自:http://blog.csdn.net/dormousenone/article/details/76570172 /** 题目:hdu6059 Kanade's trio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6059 题意:含 N 个数字的 A 数组,求有多少个三元组 (i,j,k) 满足 i<j<k 且 (Ai⊕Aj)<(Aj⊕Ak) 思路: 利用字典树维护前 k-1 个数.当前处理第 k 个数. 显然对于 k 与 i 的

【BZOJ2969】矩形粉刷 概率+容斥

[BZOJ2969]矩形粉刷 Description 为了庆祝新的一年到来,小M决定要粉刷一个大木板.大木板实际上是一个W*H的方阵.小M得到了一个神奇的工具,这个工具只需要指定方阵中两个格子,就可以把这两格子为对角的,平行于木板边界的一个子矩形全部刷好.小M乐坏了,于是开始胡乱地使用这个工具. 假设小M每次选的两个格子都是完全随机的(方阵中每个格子被选中的概率是相等的),而且小M使用了K次工具,求木板上被小M粉刷过的格子个数的期望值是多少. Input 第一行是整数K,W,H Output 一

POJ 1150 The Last Non-zero Digit 数论+容斥

POJ 1150 The Last Non-zero Digit 数论+容斥 题目地址: POJ 1150 题意: 求排列P(n, m)后面第一个非0的数. 分析: 为了熟悉题目中的理论,我先做了俩初级的题目: POJ 1401,题解见:POJ 1401 && ZOJ 2202 Factorial 阶乘N!的末尾零的个数 NYOJ 954,题解见:NYOJ 954 求N!二进制末尾几个0 这题想了一下,十进制末尾几个0可以转化为几个5因子,二进制最后一位非0可以转化为2因子,但是10进制就

bzoj2655calc 容斥+dp

2655: calc Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 322  Solved: 197[Submit][Status][Discuss] Description 一个序列a1,...,an是合法的,当且仅当: 长度为给定的n. a1,...,an都是[1,A]中的整数. a1,...,an互不相等. 一个序列的值定义为它里面所有数的乘积,即a1a2...an. 求所有不同合法序列的值的和. 两个序列不同当且仅当他们任意一位不一样.

CF449D Jzzhu and Numbers (状压DP+容斥)

题目大意: 给出一个长度为n的序列,构造出一个序列使得它们的位与和为0,求方案数 也就是从序列里面选出一个非空子集使这些数按位与起来为0. 看了好久才明白题解在干嘛,我们先要表示出两两组合位与和为0的所有情况 先hx一下每个数出现的次数,然后我们从遍历 i ,i 是二进制的数位 然后遍历所有的情况,如果第 i 位有1,那么说明我们去掉第 i 位的1就是又一种情况! 其实我们统计的是所有数在删掉/不删掉每一位的1 所有可能出现的数! 那么,状态内任意组合,不能取空集,总数就是 再根据容斥原理(最玄

HihoCoder - 1867: GCD (莫比乌斯容斥)

Sample Input 6 1 6 2 5 3 4 Sample Output 10 You are given a {1, 2, ..., n}-permutation a[1], a[2], ..., a[n]. How many pairs of integers (i, j) satisfy 1 ≤ i ≤ j ≤ n and gcd(i, j) = gcd(a[i], a[j]) = 1? Here gcd means greatest common divisor. Input F

Codeforces 611C New Year and Domino DP+容斥

"#"代表不能放骨牌的地方,"."是可以放 500*500的矩阵,q次询问 开两个dp数组,a,b,a统计横着放的方案数,b表示竖着放,然后询问时O(1)的,容斥一下, 复杂度O(n^2+q) #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmat