LC 100267. 单面值组合的第 K 小金额
https://leetcode.cn/problems/kth-smallest-amount-with-single-denomination-combination/description/
这个应该是一个比较简单的组合问题,但是之前没有系统化地考虑过怎么做,其实大致思路就是
- k = 1, 不做任何处理
- k = 2, 选择任意两个之间的lcm, 然后因为底层重复处理了,那么就需要减去
- k = 3, 选择任意三个之间的lcm, 然后因为多减去了,那么要重新添加回来
- …
这个试过其他思路好像都不行,都会存在计算错误。但是这种方法也就是适合ways = n比较少的cases. 如果N = 15的话,那么 `ops` 的数量大约是在10k左右(我估计的),外面一层二分其实就还好。
class Solution: def findKthSmallest(self, coins: List[int], k: int) -> int: def gcd(a, b): while b != 0: a, b = b, a % b return a def lcm(a, b): return (a * b) // gcd(a, b) def precompute(): ops = [] n = len(coins) for sz in range(1, n + 1): import itertools op = [] for xs in itertools.combinations(coins, sz): l = 1 for x in xs: l = lcm(x, l) op.append(l) ops.append(op) return ops ops = precompute() def test(value): res = 0 for idx, op in enumerate(ops): sign = 1 if idx % 2 == 0 else -1 r = 0 for x in op: r += value // x res += r * sign return res coins.sort() s, e = 0, k * coins[-1] while s <= e: m = (s + e) // 2 r = test(m) # print(m, r) if r >= k: e = m - 1 else: s = m + 1 return s