D. The BOSS Can Count Pairs
D. The BOSS Can Count Pairs
You are given two arrays and , both of length .
Your task is to count the number of pairs of integers such that and .
Input
Each test contains multiple test cases. The first line of input contains a single integer () — the number of test cases. The description of test cases follows.
The first line of each test case contains a single integer () — the length of the arrays.
The second line of each test case contains integers () — the elements of array .
The third line of each test case contains integers () — the elements of array .
It is guaranteed that the sum of across all test cases does not exceed .
Output
For each test case, output the number of good pairs.
Example
input
3 3 2 3 2 3 3 1 8 4 2 8 2 1 2 7 5 3 5 8 8 1 1 6 5 8 4 4 8 8 8 8 8 8 8 8 8 8 8 8 8 8
output
2 7 1
Note
In the first sample, there are good pairs:
- ,
- .
In the second sample, there are good pairs:
- ,
- ,
- ,
- ,
- ,
- ,
- .
解题思路
枚举优化题,先给出我一开始的思路。因为,因此有,所以当时就想到从开始枚举到作为的结果,记作。然后对进行约数分解,那么就会得到和。接着枚举所有值为的下标,然后再从所有值为的下标中二分出来大于的最小下标,然后在所有值为的且不超过的下标中统计数值恰好为的个数,这就是答案数对的数目。
很明显这种做法肯定会超时,需要优化的地方为统计数值恰好为的个数,但很复杂我没写出来,即便写出来时间复杂度也是,还是会超时。不过如果提前预处理每个数约数分解的结果那么计算量的分解部分就会大大降低,有可能会过。
下面给出正解。
首先我们知道了,因此必然有。由于题目中要求统计的数对要满足,但如果按照的规则来统计数对得到的答案是一样的。其中如果有且,那么我们只需交换和,可以发现得到的数对是一样的,因此接下来我们只统计的数对。
由于已经假设,因此有,所以我们从到来枚举的值(中可能不存在这个值),然后再枚举一遍序列找到大于等于的,此时就可以确定的取值,即。那么满足条件的数对数量就是序列和中满足的数量(前提是算出的要满足)。
为此我们可以先对数对以为关键字进行排序,在枚举确定每一个后开一个数组来统计数对的数量,由于已经是一个确定值,因此则表示所有并且的数对数量。由于序列已经升序排序,因此在枚举时边枚举边统计即可,当然只统计对应的。因此对于某个,满足等式的数对数量就是(下标严格小于的数对数量)。这样就可以避免重复枚举,且没有枚举到两个相同下标的情况。
AC代码如下,时间复杂度为:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 int a[N], b[N], p[N]; 9 int cnt[N]; 10 11 void solve() { 12 int n; 13 scanf("%d", &n); 14 for (int i = 0; i < n; i++) { 15 scanf("%d", a + i); 16 } 17 for (int i = 0; i < n; i++) { 18 scanf("%d", b + i); 19 } 20 for (int i = 0; i < n; i++) { 21 p[i] = i; 22 } 23 sort(p, p + n, [&](int i, int j) { 24 return a[i] < a[j]; 25 }); 26 LL ret = 0; 27 for (int i = 1; i * i <= n << 1; i++) { 28 memset(cnt, 0, n + 10 << 2); 29 for (int j = 0; j < n; j++) { 30 int t = i * a[p[j]] - b[p[j]]; 31 if (t >= 1 && t <= n) ret += cnt[t]; 32 if (i == a[p[j]]) cnt[b[p[j]]]++; 33 } 34 } 35 printf("%lld\n", ret); 36 } 37 38 int main() { 39 int t; 40 scanf("%d", &t); 41 while (t--) { 42 solve(); 43 } 44 45 return 0; 46 }
参考资料
Codeforces Round 875 (Div. 2) D (思维 + 枚举):https://zhuanlan.zhihu.com/p/633099878
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17448589.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-06-01 浙江大学-陈越、何钦铭-数据结构-习题集解析