AcWing 114.国王游戏
一、公式推导
我们对于国王身后的两个点来分析
队列可能是这样的:
左手 | 右手 | |
---|---|---|
国王 | ||
根据题意:每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
那么我们计算可得当前情况下大臣的最大金币数量:
队列也有可能是这样的
左手 | 右手 | |
---|---|---|
国王 | ||
那么我们计算可得
我们来对比一下两个答案:
令
因为,所以 ,即
因为,所以 ,即
如果想要 ,那么 ,因为上面已经知道, 所以
即:
不等式变型
消去
也就是:
也就是说,当 时,可以得到 ,也就是为了使更小,需要将较小的放在前面,我们以为关键字排序即可。
同时,由于数据范围是:
,同时 ,连乘就是 个相乘,需要用到高精度。
二、简单版本代码
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
typedef long long LL;
struct Person {
int left, right;
} person[N];
int n;
bool cmp(const Person &a, const Person &b) {
return a.left * a.right < b.left * b.right;
}
int main() {
cin >> n;
//输入
for (int i = 0; i <= n; i++)
cin >> person[i].left >> person[i].right;
//排序,注意国王不参加排序
sort(person + 1, person + 1 + n, cmp);
LL lcj = 1;//连乘积
LL res = 0;
for (int i = 0; i <= n; i++) {
//猴子选大王
res = max(res, lcj / person[i].right);
//更新连乘各
lcj *= person[i].left;
}
printf("%d", res);
return 0;
}
三、高精度版本代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n;
struct Person {
int left, right;
} person[N];
bool cmp(const Person &a, const Person &b) {
return a.left * a.right < b.left * b.right;
}
//高精度乘法
vector<int> mul(vector<int> &A, int b) {
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i++) {
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
//高精度除法
vector<int> div(vector<int> &A, int b, int &r) {
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i--) {
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}
reverse(C.begin(), C.end());
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
//获取两个vector<int>中较大的那个
vector<int> max_vec(vector<int> a, vector<int> b) {
if (a.size() > b.size()) return a;
if (a.size() < b.size()) return b;
for (int i = a.size() - 1; i >= 0; i--) {
if (a[i] > b[i]) return a;
if (a[i] < b[i]) return b;
}
return a;
}
int main() {
//优化输入
ios::sync_with_stdio(false);
cin >> n;
//输入
for (int i = 0; i <= n; i++)
cin >> person[i].left >> person[i].right;
//排序,国王不参加排序
sort(person + 1, person + n + 1, cmp);
//连乘各放入国王
vector<int> lcj;
lcj.push_back(person[0].left);
//结果
vector<int> res;
res.push_back(0);//在做高精度时,也需要进行一步初始化
for (int i = 1; i <= n; i++) {
int r;//余数,本题中因为只需要下取整,所以余数无意义
res = max_vec(res, div(lcj, person[i].right, r));
lcj = mul(lcj, person[i].left);
}
//倒序输出高精度数组中的值
for (int i = res.size() - 1; i >= 0; i--)
printf("%d", res[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2018-07-21 在Centos中安装aria2c
2016-07-21 PHP、JAVA、C#、Object-C 通用的DES加密