[R6D] 数字矩阵
- 难度 入门
- 时限 1s
- 空限 512m
- 二分计数
思路
,乘积值域只有 ,按值域计数。
用 cntA[x] 表示 中等于 的个数,prefCnt[x]、prefSum[x] 分别表示 中 的个数与和。对阈值 ,乘积 的个数与和为
每次 ,可配合二分求第 小值。
设 为第 小的值、 为第 小的值,、 分别为乘积 的个数与和:
- 时答案为 ;
- 否则答案为 。
复杂度:时间 (),空间 。
仓颉实现
import std.convert.*
import std.env.*
const MAXV: Int64 = 20000
func countSum(cntA: Array<Int64>, prefCnt: Array<Int64>, prefSum: Array<Int64>, x: Int64): (Int64, Int64) {
if (x <= 0) {
return (0, 0)
}
var cnt: Int64 = 0
var sum: Int64 = 0
for (a in 1..(MAXV + 1)) {
let ca = cntA[a]
if (ca > 0) {
var q = x / a
if (q > MAXV) {
q = MAXV
}
cnt += ca * prefCnt[q]
sum += ca * a * prefSum[q]
}
}
(cnt, sum)
}
func findV(cntA: Array<Int64>, prefCnt: Array<Int64>, prefSum: Array<Int64>, target: Int64): Int64 {
var lo: Int64 = 1
var hi: Int64 = MAXV * MAXV
while (lo < hi) {
let mid = (lo + hi) / 2
let (c, _) = countSum(cntA, prefCnt, prefSum, mid)
if (c >= target) {
hi = mid
} else {
lo = mid + 1
}
}
lo
}
main() {
let reader = getStdIn()
let l1 = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let b = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let lr = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p => Int64.parse(p) })
let l = lr[0]
let r = lr[1]
let cntA = Array<Int64>(MAXV + 1, { _ => 0 })
let cntB = Array<Int64>(MAXV + 1, { _ => 0 })
for (v in a) {
cntA[v] += 1
}
for (v in b) {
cntB[v] += 1
}
let prefCnt = Array<Int64>(MAXV + 1, { _ => 0 })
let prefSum = Array<Int64>(MAXV + 1, { _ => 0 })
for (v in 1..(MAXV + 1)) {
prefCnt[v] = prefCnt[v - 1] + cntB[v]
prefSum[v] = prefSum[v - 1] + cntB[v] * v
}
let v1 = findV(cntA, prefCnt, prefSum, l)
let v2 = findV(cntA, prefCnt, prefSum, r)
var ans: Int64 = 0
if (v1 == v2) {
ans = (r - l + 1) * v1
} else {
let (c1, _) = countSum(cntA, prefCnt, prefSum, v1 - 1)
let (c2, s2) = countSum(cntA, prefCnt, prefSum, v2 - 1)
let (c3, s3) = countSum(cntA, prefCnt, prefSum, v1)
ans = (c3 - l + 1) * v1 + (r - c2) * v2 + (s2 - s3)
}
println(ans)
}