题目:
题意:找出获得最高赏金的大臣
每一个大臣获得的赏金=国王的左手 *前面所有大臣的左手乘积/自己的右手
于是这里可以自然的想到贪心:尽可能让前面所有人的乘积更小,而自己的右手又尽可能地大,让每一个都这么排序后,找出其中获得最高赏金的大臣
(由于本题需要使用高精度,我这里使用了c++的重载运算符)
贪心思想:借用以下一位大佬的文章
交换论证显然符合这个问题
#include#include #include 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(); }



