[R24B]买糖果


数据规模:1<a<1061 < a < 10^6106b10910^6 \le b \le 10^91x1091 \le x \le 10^9

思路

三种钱币的面额为 11aabb。设使用 ii11 元、jjaa 元、kkbb 元,则凑钱条件为 i+ja+kb=xi + j \cdot a + k \cdot b = x。一旦 j,kj, k 确定,i=xjakbi = x - j \cdot a - k \cdot b 就被唯一确定(且 i0i \ge 0 等价于 ja+kbxj \cdot a + k \cdot b \le x)。所以方案数等于满足 ja+kbxj \cdot a + k \cdot b \le x 的非负整数对 (j,k)(j, k) 的个数。

直接枚举 jjkk 都可以,但复杂度取决于谁更小。注意到 a<106a < 10^6b106b \ge 10^6,于是:

0kxb109106=10000 \le k \le \left\lfloor \frac{x}{b} \right\rfloor \le \frac{10^9}{10^6} = 1000

kk 的取值很少,因此枚举 kk。对每个固定的 kk,剩余金额 rem=xkb\text{rem} = x - k \cdot b,能用的 aa 元张数 jj 的范围是 0jrem/a0 \le j \le \left\lfloor \text{rem} / a \right\rfloor,共 rem/a+1\left\lfloor \text{rem} / a \right\rfloor + 1 种。累加即可。

注意 xx 可达 10910^9jj 可达 10310^3 数量级,累加结果用 Int64 完全够,不会溢出。

复杂度

时间 O(x/b)1000O(x/b) \le 1000,空间 O(1)O(1)

仓颉实现

import std.env.*
import std.convert.*

main(): Int64 {
    let reader = getStdIn()
    let line = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
    let a = line[0]
    let b = line[1]
    let x = line[2]

    // j*a + k*b <= x,枚举 k,统计满足条件的 j >= 0 的个数
    var ans: Int64 = 0
    var k: Int64 = 0
    while (k * b <= x) {
        let rem = x - k * b
        ans += rem / a + 1
        k += 1
    }
    println(ans.toString())
    return 0
}