[NOI2007] 货币兑换

前言

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

最近这么菜一定要记住每日一练和 whk

思路

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

发现最后写了一句

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


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

rate=numAnumBnumA+RatekIPRatekAk+BknumB+IPRatekAk+Bk numBnumB+IPRatekAk+Bk

卖出相当于

profit=(numAAk+numBBk)×OP%=numB(AKrate+Bk)×OP%

一次能赚钱, 显然是要把 Ak,Bk 全部甩出去赚的最多, 买入同理

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


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

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

xi=fiRateiAiRatei+Bi yi=fiAiRatei+Bi

容易写出柿子

fi{fi1maxj[0,i)Aixj+Biyj

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


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

fi{fi1maxj[0,i)(AiRatej+Bi)fjAjRatej+Bj

fi=maxj[0,i)(AiRatej+Bi)fjAjRatej+Bjfi=(AiRatej+Bi)fjAjRatej+Bjfi=(AiRatej+Bi)fjAjRatej+Bj

根本不对

也不能找 xj,yj 的关系

fimaxj[0,i)Aixj+Biyjfimaxj[0,i)AiyjRatej+Biyjfimaxj[0,i)yj(AiRatej+Bi)


考虑

fimaxj[0,i)Aixj+Biyjfimaxj[0,i)Bi(AiBixj+yj)fiBimaxj[0,i)(AiBixj+yj)

继续转化, 记 AiBi=vi

fi=(vixj+yj)fi=vifjRatejAjRatej+Bj+fjAjRatej+Bj

可以令 x=vi,y=fi,k=fjRatejAjRatej+Bj,b=fjAjRatej+Bj 李超线段树维护

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

注意去重函数的精度问题

实现

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

总结

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

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

遇到小数可以考虑离散化

posted @   Yorg  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示