首页 技术 正文
技术 2022年11月11日
0 收藏 642 点赞 3,803 浏览 2132 个字

题意:给两个序列[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)

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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 #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;}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,084
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,559
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,408
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,181
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,818
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,901