Loading

[NOI2007] 货币兑换

前言

想起之前一道叫股票的题, 也是这么长的题面, 不过事已至此, 先读题吧

最近这么菜一定要记住每日一练和 \(\rm{whk}\)

思路

首先直觉是比例不好处理, 肯定是要转化的

发现最后写了一句

必然存在一种最优的买卖方案满足:
每次买进操作使用完所有的人民币, 每次卖出操作卖出所有的金券


有这个性质明显更好做, 每次可以钦定 \(OP = 100\) , 但是为什么呢, 考虑证明
你发现每次买入相当于对 \(num_A, num_B\) 的比例进行调整, 每次卖出相当于按照这个比例和 \(A_k, B_k\) 的比例赚钱
形式化的来讲, 买入相当于

\[rate = \frac{num_A}{num_B} \to \frac{num_A + \frac{Rate_k IP}{Rate_kA_k + B_k}}{num_B + \frac{IP}{Rate_kA_k + B_k}} \\ \ \\ num_B \gets num_B + \frac{IP}{Rate_kA_k + B_k} \]

卖出相当于

\[\begin{align*} profit & = (num_A A_k + num_B B_k) \times OP\% \\ & = num_B (A_K rate + B_k) \times OP \% \end{align*} \]

一次能赚钱, 显然是要把 \(A_k, B_k\) 全部甩出去赚的最多, 买入同理

你可以当我没有证明, 我自己也看不懂


考虑现在怎么做
你发现, 如果把 \(N\) 天分成 \(k\) 段由买入和卖出组成的时间区间 \([l, r]\) , (注意 \(l = r\) 是非法的; 同天内只考虑先卖再买, 不然没有意义) , 我们可以考虑 \(\rm{dp}\)

\(f_i\) 表示对于以 \(i\) 结尾的分段, 最优的利润 (也就是手上还有多少钱)
也就是说买 \(A, B\) 的数量为

\[x_i=\dfrac{f_iRate_i}{A_iRate_i+B_i} \\ \ \\ y_i=\dfrac{f_i}{A_iRate_i+B_i} \]

容易写出柿子

\[\begin{align*} f_i \gets \begin{cases} f_{i-1} \\ \max\limits_{j \in [0, i)} A_ix_j+B_iy_j \end{cases} \end{align*} \]

考虑第二个柿子怎么处理
你发现这种跟 \(i, j\) 都有关的东西, 拆一下转化成斜率优化的形式即可


首先化成同项, 否则就会像下面一样

\[\begin{align*} f_i \gets \begin{cases} f_{i-1} \\ \max\limits_{j \in [0, i)} \dfrac{(A_iRate_j + B_i)f_j}{A_jRate_j+B_j} \end{cases} \end{align*} \\ \]

\[\Downarrow \]

\[\begin{align*} f_i & = \max\limits_{j \in [0, i)} \dfrac{(A_iRate_j + B_i)f_j}{A_jRate_j+B_j} \\ f_i & = \dfrac{(A_iRate_j + B_i)f_j}{A_jRate_j+B_j} \\ f_i & = \dfrac{(A_iRate_j + B_i)f_j}{A_jRate_j+B_j} \end{align*} \]

根本不对

也不能找 \(x_j, y_j\) 的关系

\[f_i \gets \max\limits_{j \in [0, i)} A_ix_j+B_iy_j \\ f_i \gets \max\limits_{j \in [0, i)} A_i y_j Rate_j + B_i y_j \\ f_i \gets \max\limits_{j \in [0, i)} y_j (A_i Rate_j + B_i) \\ \]


考虑

\[f_i \gets \max\limits_{j \in [0, i)} A_ix_j+B_iy_j \\ f_i \gets \max\limits_{j \in [0, i)} B_i (\frac{A_i}{B_i} x_j + y_j) \\ f_i \gets B_i\max\limits_{j \in [0, i)} (\frac{A_i}{B_i} x_j + y_j) \\ \]

继续转化, 记 \(\frac{A_i}{B_i} = v_i\)

\[\begin{align*} f_i & = (v_i x_j + y_j) \\ f_i & = v_i\dfrac{f_jRate_j}{A_jRate_j+B_j} + \dfrac{f_j}{A_jRate_j+B_j} \\ \end{align*}\]

可以令 \(x = v_i, y = f_i, k = \dfrac{f_jRate_j}{A_jRate_j+B_j} , b = \dfrac{f_j}{A_jRate_j+B_j}\) 李超线段树维护

发现 \(x\) 可能为小数, 怎么办
我们考虑把 \(x\) 离散化对应到整数上即可, 不影响答案

注意去重函数的精度问题

实现

这种经典题要写代码, 第一道李超线段树

总结

斜率优化类问题常见的区间划分, 一般来说, 买卖问题这种两点型问题, 时间区间划分很常见

注意讨论啥也不干的情况
注意斜率优化把 \(i, j\) 都有的柿子化成同项之后再处理, 一般的方法是提出一个只与 \(i\) 相关的因式
这题也是巧妙地转化, 人类智慧美丽时刻

遇到小数可以考虑离散化

posted @ 2025-01-15 17:09  Yorg  阅读(19)  评论(0)    收藏  举报