[R24C]开关控制
对于 的数据,;对于 的数据,,。
思路
两个机器人都在 之间往返,运动周期均为 。在第 秒按下起点开关,之后每秒移动一步并按下新位置的开关,因此从第 秒到第 秒共有 次操作。
考虑机器人 1 的位置序列:,正好是一个长度为 的周期。机器人 2 从 出发、方向相反,但其位置序列恰好是机器人 1 位置的「镜像」——在任意时刻 ,机器人 2 的位置 。于是开关 被按下的总次数为
其中 是机器人 1 在 个时刻里经过位置 的次数。
关键观察:一个完整周期对每个位置的贡献总是偶数次(端点 、 每周期各 次,中间位置每周期各 次,累加到两个机器人后均为偶数)。因此完整周期不改变任何开关状态的奇偶性,只需考察余下 个时刻()。
在这余下的 个时刻里,机器人 1 的轨迹为 ,最多走到位置 ;当 时,已经掉头,会再次覆盖中间位置 。因此:
- 上升段:位置 时 加 ;
- 下降段:当 且 且 时 再加 。
求出 与 后,若二者之和为奇数则该开关处于开启状态。统计所有奇数 cnt 的个数即为答案。
当 (即 恰为周期整数倍)时,所有开关都被按偶数次,答案为 。
复杂度
- 时间:,对每个开关 计算。
- 空间:,无需存储数组。
仓颉实现
import std.env.*
import std.convert.*
main(): Int64 {
let reader = getStdIn()
let parts = reader.readln().getOrThrow().split(" ", removeEmpty: true)
let n = Int64.parse(parts[0])
let k = Int64.parse(parts[1])
let T = 2 * (n - 1)
let total = k + 1
let m = total % T
if (m == 0) {
println("0")
return 0
}
// g(i): robot1 visits to position i during remainder moments t=0..m-1.
// Position path over one period: 1,2,...,n,n-1,...,2 (length T).
// Ascending phase covers positions [1, min(m,n)]; descending phase (m>n)
// covers interior positions [2n-m, n-1] once more.
let ascMax = if (m < n) { m } else { n }
let descLo = 2 * n - m
var ans: Int64 = 0
for (i in 1..n + 1) {
var gi: Int64 = 0
if (i <= ascMax) {
gi += 1
}
if (i >= 2 && i <= n - 1 && m > n && i >= descLo) {
gi += 1
}
let j = n + 1 - i
var gj: Int64 = 0
if (j <= ascMax) {
gj += 1
}
if (j >= 2 && j <= n - 1 && m > n && j >= descLo) {
gj += 1
}
if (((gi + gj) % 2) != 0) {
ans += 1
}
}
println(ans)
return 0
}