目录
[4.1 问题在哪](#4.1 问题在哪)
[4.2 我们要写两个高精度操作](#4.2 我们要写两个高精度操作)
[4.3 高精度存储规则](#4.3 高精度存储规则)
[4.4 高精度 大数 × 小整数 函数](#4.4 高精度 大数 × 小整数 函数)
[4.5 高精度 大数 ÷ 小整数 函数](#4.5 高精度 大数 ÷ 小整数 函数)
[5. 大数比较,找最大值](#5. 大数比较,找最大值)
[6. 完整代码](#6. 完整代码)
1.题目
洛谷P1080 国王游戏(贪心 邻项交换法的例题)
https://www.luogu.com.cn/problem/P1080


2.定义结构体存数据
每个大臣有左手数a、右手数b,用结构体统一管理

3.贪心排序规则

此解析来自:
解析贪心思想
https://oi-wiki.org/basic/greedy/
结论
两个大臣 x、y
若 x.a * x.b < y.a * y.b,则 x 排在 y 前面。
全局所有大臣按这个规则升序排序,就是最优排队顺序

1LL 防止相乘 int 溢出,转成长整型计算
之后直接调用:sort(大臣数组, 大臣数组+n, cmp);
4.乘积太大存不下:用高精度
4.1 问题在哪
国王左手 + 几十个大臣左手不断相乘数值轻松突破 long long 上限,普通变量直接溢出报错 必须用数组模拟大整数(高精度)
4.2 我们要写两个高精度操作
- 大数 × 小整数作用:不断把前缀总乘积,乘上当前大臣左手
- 大数 ÷ 小整数作用:前缀乘积 ÷ 大臣右手,算出金币数
4.3 高精度存储规则
用一维数组存大数,低位存在数组下标小的位置 例:数字 1234存成:num[0]=4 , num[1]=3 , num[2]=2 , num[3]=1方便进位、借位运算
4.4 高精度 大数 × 小整数 函数

作用:遍历完一个大臣,前缀乘积要乘上该大臣左手数,更新总乘积
逻辑:逐位相乘 + 进位,从低位往高位算
4.5 高精度 大数 ÷ 小整数 函数

注:
1 .memset(res, 0, sizeof(res)); (memset 是 C/C++ 专门用来给内存赋值的函数)
这一行代码 = 给数组 "清零",因为上一组的数组还留在这里呢,memset( 数组名, 要填的值, 填多大空间 );
2 .reverse(res, res + res_len); (把一段数据的顺序 从头到尾反转)
字符串:reverse(起始位置, 结束位置); eg: reverse(s.begin(),s.end());
数组:reverse(数组名, 数组名 + 长度); eg: reverse(arr, arr + len);
3 .除法从高位向低位算
4.作用:前缀总乘积 ÷ 大臣右手数 = 该大臣金币
5.要求:返回商,向下取整,同时保留原大数不变(只用来算奖金,不修改乘积)
5. 大数比较,找最大值
我们每次算出一个大臣的奖金(大数),要和当前最大奖金对比,更新最大值

len_a:第一个大数的位数
len_b:第二个大数的位数
6. 完整代码
主函数完整流程:
- 读入 n
- 读国王左手 king_a、右手 king_b
- 读入 n 个大臣存入数组
- 调用 sort 按贪心规则排序
- 高精度数组初始化,存入国王左手数字
- 初始化最大奖金大数
- 循环遍历每一位大臣:
- 大数乘积 ÷ 当前大臣右手 → 得到金币
- 和最大值比较,更新最大值
- 大数乘积 × 当前大臣左手,更新前缀乘积
- 倒序输出最大奖金数组
代码:




注:本题部分讲解内容来源为豆包,请注意甄别