1. 题目背景与问题解析
这道题目源自2012年全国青少年信息学奥林匹克竞赛(NOIP)提高组的真题,属于典型的贪心算法与高精度计算结合的应用题。题目设定在一个虚构的王国中,国王邀请n位大臣参与游戏,每位大臣左右手上各写有一个正整数。游戏规则要求所有大臣排成一列,国王始终站在队伍最前面。每位大臣获得的金币数等于其前面所有人左手数字的乘积除以自己右手数字的商。
问题的核心在于:如何安排大臣的排列顺序,使得获得最多金币的大臣得到的金币数尽可能少。这实际上是一个优化问题,需要找到最优的排列策略,并处理可能的大整数运算。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法思路与证明
2.1 贪心策略的直觉
面对这类排列优化问题,我们首先考虑贪心算法。直觉上,我们希望将右手数字较大(会导致分母较大)的大臣尽量往后排,而左手数字较小(对后续乘积影响小)的大臣也尽量往后排。这引导我们考虑将大臣按照某种与左右手数字相关的指标进行排序。
2.2 关键排序规则的推导
经过数学推导,我们可以证明最优排列应该按照每位大臣左手与右手数字的乘积从小到大排序。具体证明如下:
假设有两个相邻大臣i和j,i在前,他们的左右手数字分别为(li, ri)和(lj, rj)。交换他们位置不会影响其他大臣的金币数,只需要考虑这两个大臣获得金币的最大值。
交换前:
- 大臣i获得金币:L / ri (L是i前面所有人左手乘积)
- 大臣j获得金币:(L * li) / rj
交换后:
- 大臣j获得金币:L / rj
- 大臣i获得金币:(L * lj) / ri
为了不使交换后的最大值更大,需要满足:
max(L/ri, (Lli)/rj) ≤ max(L/rj, (Llj)/ri)
这等价于要求 li * ri ≤ lj * rj。因此,按照li*ri的升序排列可以保证局部最优,进而达到全局最优。
3. 实现细节与高精度处理
3.1 基本算法框架
- 读取所有大臣的左右手数字
- 按照左手与右手数字的乘积升序排序
- 模拟游戏过程,计算每位大臣获得的金币数
- 找出最大值输出
3.2 高精度计算的必要性
由于左手数字的乘积可能非常大(最多1000个10000相乘,约有40000位数字),普通数据类型无法存储,必须实现高精度乘法和高精度除法(实际只需要
