[R24B]买糖果


数据规模:1<a<1061 < a < 10^6,106≤b≤10910^6 \le b \le 10^9,1≤x≤1091 \le x \le 10^9。

思路

三种钱币的面额为 11、aa、bb。设使用 ii 枚 11 元、jj 枚 aa 元、kk 枚 bb 元,则凑钱条件为 i+j⋅a+k⋅b=xi + j \cdot a + k \cdot b = x。一旦 j,kj, k 确定,i=x−j⋅a−k⋅bi = x - j \cdot a - k \cdot b 就被唯一确定(且 i≥0i \ge 0 等价于 j⋅a+k⋅b≤xj \cdot a + k \cdot b \le x)。所以方案数等于满足 j⋅a+k⋅b≤xj \cdot a + k \cdot b \le x 的非负整数对 (j,k)(j, k) 的个数。

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

0≤k≤⌊xb⌋≤109106=10000 \le k \le \left\lfloor \frac{x}{b} \right\rfloor \le \frac{10^9}{10^6} = 1000

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

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

复杂度

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

仓颉实现

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

main() {
    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)
}