abc 231 e 题解
abc 231 e
题意
有 \(n\) 种硬币,面值分别为 \(A_1, A_2, \dots A_N\) 元,其中 \(1 = A_1 < A_2 < A_3 \dots < A_N\),并且对于 \(1 \le i \le N - 1\) 的所有 \(i\) 都有 \(A_{i + 1}\) 是 \(A_i\) 的倍数。
现在要用这些硬币支付 \(X\) 元,请你求出支付和找零的硬币数量的和的最小值。
-
\(1 \le N \le 60\)
-
\(1 = A_1 < \dots < A_N \le 10 ^ {18}\)
-
\(1 \le X \le 10 ^ {18}\)
思路
首先,这个题目有一个很明显会超时还有可能会爆空间的做法,完全背包。
\(dp_i\) 表示凑出 \(i\) 元的最少硬币数量。
转移为
因为支付的钱数最多为 \(2 \times X\) 元(如果支付 \(2 \times X\) 元,就需要找零 \(X\) 元,也是凑出 \(X\) 元,还需要额外加上凑出 \(2 * X\) 元的硬币数量,很明显会比直接凑出 \(X\) 元更差),所以空间复杂度为 \(O(2 \times X)\)。
但是 \(X\) 有 \(10 ^ {18}\) 那么大,根本不能用数组存下来,所以我们可以用 map 来实现。
但是,就算空间的问题解决了,时间也救不回来。
dp
的时间复杂度为 \(O(2 \times X)\),也就是 \(O(X)\)。
计算答案的时间复杂度为 \(O(X)\)。
总时间复杂度为 \(O(X)\),完全无法接受。
所以,我们要考虑其他方法。
其实可以发现,题目中几乎所有条件我们都用上了,但还有一句话: 对于 \(1 \le i \le N - 1\) 的所有 \(i\) 都有 \(A_{i + 1}\) 是 \(A_i\) 的倍数。 这句话我们一直都没有用上,那么,这又代表了什么呢?
题目里还有一个条件: \(1 = A_1 < A_2 < A_3 \dots < A_N\)
。
这代表着任何一个数都可以被表示出来,而又有 \(A_{i + 1}\) 是 \(A_i\) 的倍数这个条件,所以可以发现,我们可以将 \(X\) 变成一个不知道是什么进制的数,而它对应的硬币数量就是他各位数字之和。
所以我们可以列这样一个表格:
令 \(B_i = A_{i + 1} \div A_i (1 \le i \le N - 1)\)
位号 | N | \(\dots\) | 2 | 1 | 0 |
---|---|---|---|---|---|
位权 | \(A_N\) | \(\dots\) | \(A_3\) | \(A_2\) | \(A_1\) |
数值 | \(C_N = x \div B_1 \dots \div B_N\) | \(\dots\) | \(C_3 = x \div B_1 \div B_2 \mod B_3\) | \(C_2 = X \div B_1 \mod B_2\) | \(C_1 = X \mod B_1\) |
所以,对于第 \(i\) 位来说,这意味可以选择用 \(C_i\) 个 \(A_i\),也可以用 \(1\) 个 \(A_{i + 1}\) 和 \(B_i - C_i\) 个 \(A_i\)。
\(dp_{i, 0 / 1}\) 表示用前 \(i\) 种硬币凑出(不出)前 \(i\) 位所用的硬币的最小数量(描述的很奇怪)
所以有转移:
来解释一下吧,就是如果第 \(i\) 位要用 \(C_i\) 个 \(A_i\) 来凑的话,那么就直接取上一位的最小硬币数量,再加上 \(C_i\) 即可。
那么,这里就有一个问题了,如果第 \(i - 1\) 位是用 \(1\) 个 \(A_i\) 和 \(B_{i - 1} - C_{i - 1}\) 个 \(A_{i - 1}\) 凑出来的话,\(dp_{i - 1, 1}\) 不应该在加 \(1\) 吗?
这么想也没问题,主要是写法的不同,我是把这个 \(1\) 放在 \(dp_{i - 1, 1}\) 中加的。
我们先看 \(dp_{i - 1, 0} + 1\),这里的 \(dp_{i - 1, 0}\) 就是第 \(i - 1\) 位不借位的最少硬币数量,再 \(+ 1\) 则是因为当前这一位要再借一位。
再看 \(dp_{i - 1, 1} - 1\),这个就有一点点不好懂了。
我们先将这个转移换一种方式写出来:
其实这个式子应该是 \(dp_{i - 1, 1} - 1 + 1 + (B_i - C_i - 1)\),第一个 \(- 1\) 是因为在前 \(i - 1\) 位已经借过一次了,而这里又要借,所以要把之前借的那一位先去掉,\(+ 1\) 是因为又要再借一位,\(B_i - C_i - 1\) 是第 \(i\) 种硬币需要找零的数量,因为第 \(i - 1\) 位借了一个,所以第 \(i\) 位所需要的硬币数量就变成 \(C_i + 1\) 了,所以就是 \(B_i - (C_i + 1)\),也就是 \(B_i - C_i - 1\)。
所以总时间复杂度为 \(O(n)\),空间复杂度为 \(O(n)\)。