1 条题解
-
0
题目回顾
我们有一个长度为 的数组 ,以及两个整数 和 。
一对下标 满足 被称为 美丽对,当且仅当:- 能被 整除;
- 能被 整除。
要求计算美丽对的数量。
条件转化
第一步:整除条件的等价形式
条件 1:
等价于:
因此:
$$a_i \bmod x + a_j \bmod x = 0 \quad \text{或} \quad x $$即:
条件 2:
等价于:
因此:
第二步:关键观察
对于固定下标 ,所有与 构成美丽对的下标 ()必须同时满足:
这意味着,如果我们把每个元素 映射成一个键值对:
那么对于当前的 ,我们需要在之前出现过的元素中,找到所有键等于:
$$\left( (x - (a_j \bmod x)) \bmod x,\; a_j \bmod y \right) $$的元素个数。
算法步骤
- 初始化一个空字典(或哈希表)
cnt,用来存储键值对(a_i mod x, a_i mod y)的出现次数。 - 遍历数组 中的每个元素 (作为 ):
- 计算:
- 计算需要的第一个余数:
- 查询
cnt中键(need_x, yy)的值,加到答案ans中。 - 将当前元素对应的键
(xx, yy)在cnt中的计数加 1。
- 输出
ans。
时间复杂度
- 每个元素处理 次哈希表操作。
- 总复杂度 每个测试用例,所有测试用例总和 ,满足 的限制。
C++ 代码实现
#include <iostream> #include <vector> #include <map> using namespace std; void solve() { int n, x, y; cin >> n >> x >> y; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } map<pair<int, int>, int> cnt; long long ans = 0; for (int e : a) { int xx = e % x; int yy = e % y; int need_x = (x - xx) % x; ans += cnt[{need_x, yy}]; cnt[{xx, yy}]++; } cout << ans << endl; } int main() { int t; cin >> t; while (t--) { solve(); } return 0; }
示例验证
以题目第一个样例为例:
输入:
6 5 2 1 2 7 4 9 6过程:
匹配数 累计答案 1 4 0 2 2 0 3 7 1 4 4 0 1 9 1 1 1 6 1 0 4 2 输出
2,与题目一致。
总结
本题的核心在于将复杂的整除条件转化为对余数对的匹配问题,并通过哈希表在前缀中快速查找。
- 1
信息
- ID
- 6412
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者