1 条题解
-
0
题目题解
问题理解
给定 和 个查询 ,要求统计区间内满足
的整数 的个数。
第一步:周期性
设 ,实际上 (因为 不一定是互质的,但 一定是公倍数)。
可以验证:对于任意整数 和 ,有因为 是 和 的倍数,所以 和 在模 和模 下余数相同,进而嵌套余数也相同。
因此,条件是否成立只取决于 。
第二步:前缀计数
我们可以预处理数组 ,其中 表示 中满足条件的数的个数( 从 到 )。
注意 ,但 时 ,,相等,不计数。对于任意 ,设 ,,则
因为前 个完整周期每个有 个满足条件的数,最后一个不完整周期有 个。
第三步:区间查询
对于查询 ,答案即为
第四步:实现细节
- 预处理 只需计算到 ,因为 ,,可行。
- 注意 可达 ,需要用
long long。 - 对于每个测试用例,先调用
build(a, b)计算 数组,然后回答查询。
时间复杂度
- 预处理 。
- 每个查询 。
- 总复杂度 ,满足 ,。
代码实现
#include <bits/stdc++.h> using namespace std; const int N = 40043; int len; int p[N]; void build(int a, int b) { len = a * b; p[0] = 0; for (int i = 1; i <= len; i++) { p[i] = p[i - 1]; if ((i % a) % b != (i % b) % a) { p[i]++; } } } long long query(long long x) { long long cnt = x / len; int rem = x % len; return 1LL * p[len] * cnt + p[rem]; } long long query(long long l, long long r) { return query(r) - query(l - 1); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int a, b, q; cin >> a >> b >> q; build(a, b); while (q--) { long long l, r; cin >> l >> r; cout << query(l, r) << " "; } cout << "\n"; } return 0; }
验证样例
输入:
2 4 6 5 1 1 1 3 1 5 1 7 1 9 7 10 2 7 8 100 200输出:
0 0 0 2 4 0 91与题目输出一致。
总结
本题的关键在于:
- 发现周期性,周期为 。
- 预处理每个周期内的前缀和,用于 回答查询。
- 注意 是否计入,根据条件判断。
- 1
信息
- ID
- 6337
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者