[R54E]二元组和四元组
数据规模:,,,。
思路
固定整数 ,设恰好有 个 满足 。那么 有 种选择, 有 种选择,所以满足 的二元组 共有:
当 时, 不变,这一段中共有 个整数 。同理,若 ,满足 的二元组 共有 个。因此该 的权值是:
枚举 。记 ,则需要找到所有满足:
的 。函数 在 上单调递增,并且关于 对称。若左半段中最小的合法位置为 ,那么所有合法位置恰好构成连续区间:
可以二分求出 。这些位置对应的整数 的数量为相邻差之和,即:
将它乘上当前区间内整数 的数量 ,再对所有 求和即可。实现中用 计算上取整,避免乘积 超出 Int64。
复杂度
时间复杂度为 ,空间复杂度为 。
仓颉实现
查看仓颉实现
import std.convert.*
import std.env.*
func countValidY(b: Array<Int64>, m: Int64, need: Int64): Int64 {
let half = m / 2
if (half * (m - half) < need) {
return 0
}
var left = Int64(1)
var right = half
while (left < right) {
let mid = (left + right) >> 1
if (mid * (m - mid) >= need) {
right = mid
} else {
left = mid + 1
}
}
return b[m - left] - b[left - 1]
}
main() {
let reader = getStdIn()
let first = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let n = first[0]
let m = first[1]
let v = first[2]
let a = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let b = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
var answer = Int64(0)
var p = Int64(1)
while (p < n) {
let pairCount = p * (n - p)
let need = (v - 1) / pairCount + 1
let xCount = a[p] - a[p - 1]
answer += xCount * countValidY(b, m, need)
p += 1
}
println(answer)
}