[R49B]减法


数据规模:1≤k≤1001 \le k \le 100,1≤x≤10k−11 \le x \le 10^k - 1。

思路

10k−110^k - 1 是 kk 个 9 组成的数,例如 k=3k = 3 时为 999999。用 999⋯9999\cdots9 减去 xx,等价于求 xx 的 9 的补数:把 xx 左侧补前导零到 kk 位,再让每一位 dd 变成 9−d9 - d。例如 999−123=876999 - 123 = 876,每位正是 9−1=89-1=8、9−2=79-2=7、9−3=69-3=6。

注意当 x=10k−1x = 10^k - 1(即 kk 个 9)时,每一位补数都是 00,结果为 00;最高位也可能产生前导零,因此最后需要去掉前导零、至少保留一个数字。

由于 kk 最大为 100100,结果可达 1010010^{100} 量级,超出整数范围,全程用字符串 / 字节数组处理即可。

复杂度

时间 O(k)O(k),空间 O(k)O(k)。

仓颉实现

查看仓颉实现
import std.env.*
import std.convert.*

main() {
    let reader = getStdIn()
    let parts = reader.readln().getOrThrow().split(" ", removeEmpty: true)
    let k = Int64.parse(parts[0])
    let xStr = parts[1]
    let xLen = Int64(xStr.size)
    // 把 x 左补前导 '0' 到 k 位
    let builder = StringBuilder()
    var i = 0
    while (i < k - xLen) {
        builder.append(r'0')
        i++
    }
    builder.append(xStr)
    let padded = builder.toString()
    // 每位做 9 的补数:结果位 = '9' - (c - '0')
    let out = Array<UInt8>(k, { idx: Int64 =>
        let c = padded[idx]
        57u8 - (c - 48u8)
    })
    // 去掉前导零,保留至少一个数字
    var start = 0
    while (start < k - 1 && out[start] == 48u8) {
        start++
    }
    let s = start
    let trimmed = Array<UInt8>(k - s, { idx: Int64 => out[s + idx] })
    println(String.fromUtf8(trimmed))
}