题目:
题意:找出获得最高赏金的大臣
每一个大臣获得的赏金=国王的左手 *前面所有大臣的左手乘积/自己的右手
于是这里可以自然的想到贪心:尽可能让前面所有人的乘积更小,而自己的右手又尽可能地大,让每一个都这么排序后,找出其中获得最高赏金的大臣
(由于本题需要使用高精度,我这里使用了c++的重载运算符)
贪心思想:借用以下一位大佬的文章
交换论证显然符合这个问题
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct node
{
int left;
int right;
}s[10002];
class int_L
{
public:
int DATA[10002];
int_L()
{//构造器
memset(DATA, 0, sizeof(DATA));
DATA[0] = 1; //data数组首位表示位数
}
int_L(int k)
{
int i;
memset(DATA, 0, sizeof(DATA));
for (i = 1;k != 0;i++)
{
DATA[i] = k % 10; //DATA数组存储从低位数到高位数
k /= 10;
}
DATA[0] = i - 1; //DATA[0]存储位数
}
int_L operator+ (const int_L& b) //重构加号
{
int_L a;
int x = 0;
int maxn = max(b.DATA[0], DATA[0]);
for (int i = 1;i <= maxn + 1;i++)
{
a.DATA[i] = b.DATA[i] + DATA[i] + x;
x = a.DATA[i] / 10;
a.DATA[i] %= 10;
}
if (a.DATA[maxn + 1] == 0)
a.DATA[0] = maxn;
else
a.DATA[0] = maxn + 1;
return a;
}
bool operator<(const int_L& b) //重载<
{
if (DATA[0] < b.DATA[0])
return true;
if (DATA[0] == b.DATA[0]) //位数相等,找到不同的数字为止
{
int i = DATA[0];
while (DATA[i] == b.DATA[i])
i--;
//一直寻找,直到找到不同的数字为止
//如果这一位数DATA比较小,就返回真
return DATA[i] < b.DATA[i] ? true : false;
}
return false;
}
int_L operator- (const int_L& b) //重载减号
{ //减法必须保证DATA中的数子比b.data的数字大
int_L a;
int flag = 0;
int maxn = max(b.DATA[0], DATA[0]);
if (*this < b)
{
flag = 1;
}
for (int i = 1;i <= maxn;i++)
{
if (flag)
a.DATA[i] = b.DATA[i] - DATA[i];
else
a.DATA[i] = DATA[i] - b.DATA[i];
if (a.DATA[i] < 0)
{
a.DATA[i + 1]--; //借一位
a.DATA[i] += 10;
}
}
int i;
for (i = maxn;i > 0;i--)
if (a.DATA[i] != 0)
break;
a.DATA[0] = i;
if (a.DATA[1] == 0 && i == 0) a.DATA[0] = 1;
if (flag)
a.DATA[0] *= -1;
return a;
}
int_L operator *(const int b) //这里只重载了大位数*小位数
{
int_L a;
int x = 0;
for (int i = 1;i <= DATA[0];i++)
a.DATA[i] = DATA[i] * b; //模拟乘法,直接从低位数开始乘
a.DATA[0] = DATA[0];
int i;
for (i = 1;i <= a.DATA[0] || a.DATA[i];i++) //判断循环条件是:要么不满最大长度,要么a最高项不为0
{
a.DATA[i + 1] += a.DATA[i] / 10;
a.DATA[i] %= 10;
}
a.DATA[i] ? a.DATA[0] = i : a.DATA[0] = i - 1;
return a;
}
int_L operator /(const int b)
{//高精度数除低精度数
/*思路:这里运用的是一种存储的方法,如果这个数<即将除的数,就
从最高位开始模拟,模拟的是竖式运算
*/
int res = 0;
int_L a;
for (int i = DATA[0];i > 0;i--)
{ //最高位开始,模拟竖式计算
res = res * 10 + DATA[i];
a.DATA[i] = res / b;
res %= b;
}
int i = DATA[0];
while (a.DATA[i] == 0)
i--;
a.DATA[0] = i;
return a;
}
void print()
{
if (DATA[0] < 0)
{
cout << '-';
DATA[0] *= -1;
}
for (int i = DATA[0];i >= 1;i--)
cout << DATA[i];
}
};
bool cmp(node a, node b)
{
return a.left * a.right < b.left* b.right ? true : false;
}
int main()
{
int n;
cin >> n; //输入大臣个数
int a, b;
cin >> a >> b;
for (int i = 0;i < n;i++)
scanf_s("%d%d", &s[i].left, &s[i].right);
sort(s, s + n, cmp);
int_L k(a);
int_L ans(1);
int_L temp;
for (int i = 0;i < n;i++)
{
temp =k/ s[i].right;
if (ans < temp) //答案比k小,就让答案更新
{
ans = temp;
}
k = k * s[i].left;
}
ans.print();
}