[R2D] 倍数问题
- 难度 普及/提高-
- 时限 2s
- 空限 512m
- 数论数学
数据规模:,。
思路
记 为 中值为 的项数,则询问 的答案是 。
对每个 暴力枚举倍数会超时,改为类似 埃氏筛 的预处理:对每个 ,累加 得到 。总枚举量约为 , 时约 次加法。
之后每个询问 回答。
复杂度:时间 ,空间 。
仓颉实现
import std.env.*
import std.convert.*
const MAXV = 500000
main(): Int64 {
let reader = getStdIn()
let n = Int64.parse(reader.readln().getOrThrow())
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
var num = Array<Int64>(MAXV + 1, { _ => 0 })
for (i in 0..n) {
num[a[i]] += 1
}
var ans = Array<Int64>(MAXV + 1, { _ => 0 })
for (i in 1..=MAXV) {
var s: Int64 = 0
var j = i
while (j <= MAXV) {
s += num[j]
j += i
}
ans[i] = s
}
let q = Int64.parse(reader.readln().getOrThrow())
var sb = StringBuilder()
for (_ in 0..q) {
let x = Int64.parse(reader.readln().getOrThrow())
sb.append(ans[x].toString())
sb.append("\n")
}
print(sb.toString())
return 0
}
要点:
- 值域只有 ,直接开数组计数,不需要排序或哈希。
- 询问有 个,答案用
StringBuilder拼接后一次性输出,避免逐行println的开销。