思路:
首先我们清楚,交换任意两个相邻大臣的位置,对其他大臣获得的金币数不会造成影响。题目要求使得获得奖赏最多的大臣,所获奖赏尽可能的少,也就是让最大值尽可能小,并且国王固定在队伍的最前面,所以我们考虑后面的大臣即可。
在n(n≥2)个大臣中找出任意相邻的两个大臣A与B,记他们左右手的值分别为 、
、
、
,以及在A之前的所有大臣和国王左手上数字的乘积为
| 前乘积 | A | B |
|---|---|---|
假如此时A和B获得的金币数的最大值最小,则我们有不等式 , 即A、B获得的金币数的最大值小于等于交换位置后B、A获得的金币数的最大值
很显然:
结合上面的不等式,我们可以推断出:
化简得到:
所以,我们只需要对大臣们进行排序,让他们满足上面化简得到的不等式,
排序完了以后再从第一个大臣开始遍历,找到最多需要多少个金币即可
代码
*对于 100%的数据,有 1 ≤ n ≤1,000,0 < a,b < 10000。数据过大,这里无耻的复制了别人的大数计算的代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct people {
int leftHand; //左手上的数
int rightHand; //右手上的数
} people;
//需要用到大数计算
//一个大数乘一个int数
//返回num1 * num2
vector<int> multiply(const vector<int> &num1, int num2) {
int carry = 0; //记录进位
vector<int> ans; //记录答案
for (int i = 0; i < num1.size() || carry != 0; ++i) {
//如果还在num1的范围内,和num1相乘一位
if (i < num1.size()) {
carry += num1[i] * num2;
}
ans.push_back(carry % 10);
carry /= 10;
}
return ans;
}
//一个大数除一个int
//返回 num1 / num2
vector<int> divide(const vector<int> &num1, int num2) {
int temp = 0; //工具人变量,用来做除法
vector<int> ans; //记录答案
//倒着循环,因为大数是倒着记的
for (int i = num1.size() - 1; i >= 0; --i) {
temp = temp * 10 + num1[i];
ans.push_back(temp / num2);
temp %= num2;
}
//因为大数是倒着记的,所以输出的答案也要倒过来,顺便把前面多出来的0删掉
reverse(ans.begin(), ans.end());
while (ans.back() == 0 && ans.size() > 1) {
ans.pop_back();
}
return ans;
}
//判断num1是否大于num2
bool operator>(const vector<int> &num1, const vector<int> &num2) {
//如果num1和num2位数不同,位数多的数更大
if (num1.size() != num2.size()) {
return num1.size() > num2.size();
}
for (int i = num1.size() - 1; i >= 0; --i) {
if (num1[i] != num2[i]) {
return num1[i] > num2[i];
}
}
return false;
}
//输出大数
ostream &operator<<(ostream &output, vector<int> &num) {
for (int i = num.size() - 1; i >= 0; --i) {
output << num[i];
}
return output;
}
int main() {
int temp; //工具人变量
int n; //总人数(国王+大臣)
cin >> n;
n++;
people pps[n]; //pps[0]为国王,其他为大臣
for (int i = 0; i < n; ++i) {
cin >> temp;
pps[i].leftHand = temp;
cin >> temp;
pps[i].rightHand = temp;
}
//对大臣进行排序,让最大的金币数最少
for (int i = 1; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (pps[i].leftHand * pps[i].rightHand > pps[j].leftHand * pps[j].rightHand) {
swap(pps[i], pps[j]);
}
}
}
vector<int> coins, maxCoins; //金币数和最大金币数
coins.push_back(pps[0].leftHand);
for (int i = 1; i < n; ++i) {
vector<int> tempCoins = divide(coins, pps[i].rightHand); //第i个大臣的金币数
if (tempCoins > maxCoins || maxCoins.empty())maxCoins = tempCoins;
coins = multiply(coins, pps[i].leftHand);
}
cout << maxCoins;
}
京公网安备 11010502036488号