[R76C] 这回不是站点了
数据规模:,。
思路
记第 列(从 开始编号)的位权为 ,第 行第 列的字符为 ,第 列中 1 的个数为 。原得分为
交换带来的增量。 选定 交换后,对第 行来说,只有第 、 两位换了值:第 位由 变成 ,第 位由 变成 。于是这一行的得分变化是
对所有行求和:
这里用到了 。关键结论:增量只取决于两列各自 1 的个数 和位权差,与两列是否在同一些行上同时为 1 完全无关。
答案。 必须交换且不能不操作,所以枚举所有 取最大的增量即可:
注意增量可以为负(样例 2 就是 ),取最大值自然覆盖这种情况;由于 至少存在一对列,不会没有候选。
复杂度
时间 ,空间 。
仓颉实现
查看仓颉实现
import std.env.*
import std.convert.*
main() {
let reader = getStdIn()
let hw = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let h = hw[0]
let w = hw[1]
let cnt = Array<Int64>(w, { _ => 0 })
var r: Int64 = 0
while (r < h) {
let s = reader.readln().getOrThrow()
var j: Int64 = 0
while (j < w) {
if (Int64(s[j]) == 49) {
cnt[j] += 1
}
j += 1
}
r += 1
}
let pw = Array<Int64>(w, { _ => 0 })
var k: Int64 = 0
while (k < w) {
pw[k] = 1 << (w - 1 - k)
k += 1
}
var base: Int64 = 0
k = 0
while (k < w) {
base += cnt[k] * pw[k]
k += 1
}
var best: Int64 = -(1 << 62)
var i: Int64 = 0
while (i < w) {
var j: Int64 = i + 1
while (j < w) {
let delta = (pw[i] - pw[j]) * (cnt[j] - cnt[i])
if (delta > best) {
best = delta
}
j += 1
}
i += 1
}
println(base + best)
}