NC16561-国王的游戏
链接:https://ac.nowcoder.com/acm/problem/16561
来源:牛客网
国王的游戏
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入描述:
第一行包含一个整数 n ,表示大臣的人数。
第二行包含两个整数 a 和 b ,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b ,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出描述:
一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
输入
3 1 1 2 3 7 4 4 6
输出
2
说明
按 1 、 2 、 3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2 ;
按 1 、 3 、 2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2 ;
按 2 、 1 、 3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2 ;
按 2 、 3 、 1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9 ;
按 3 、 1 、 2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2 ;
按 3 、 2 、 1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9 。
因此,奖赏最多的大臣最少获得 2 个金币,答案输出 2 。
备注:
对于 20%的数据,有 1 ≤ n ≤ 10 < a,b < 8 ;
对于 40%的数据,有 1 ≤ n ≤ 20 <a,b<8 ;
对于 60%的数据,有 1 ≤ n ≤ 100 ;
对于 60%的数据,保证答案不超过 109 ;
对于 100%的数据,有 1 ≤ n ≤1,000 < a,b < 10000 。
转:https://ac.nowcoder.com/acm/problem/blogs/16561
类似xxxABxxx的排列1,如果前面的xxx左边乘积为sum,LA表示A的左手,RA表示A的右手,那么A的奖赏是:sum / RA, B的是:sum * LA / RB, 两者最大max(sum / RA, sum * LA / RB)
类似xxxBAxxx的排列2,如果前面的xxx左边乘积为sum,LA表示A的左手,RA表示A的右手,那么A的奖赏是:sum * LB / RA, B的是:sum / RB, 两者最大max(sum / RB, sum * LB / RA)
如果1小于2,那么max(sum / RA, sum * LA / RB) <= max(sum / RB, sum * LB / RA),因为sum * LB / RA 恒大于 sum / RA,所以排列2只能选sum * LB / RA,因为sum * LB / RA 恒大于 sum / RA,所以sum / RB 恒小于排列2,故只要满足sum * LA / RB <= sum * LB / RA即可保证排列1小于等于排列2,原式可化简为LA * RA <= LB * RB,故在AB中左*右越小应该越靠前(因为我们是要使得最大值最小)。
考虑一个Ln*Rn的递增数列,如果随意交换任意两个相邻的(交换不相邻的情况例如交换i,j可以考虑成从j到i+1依次与其的前一个交换),则必定使得最大值可能发生改变,而且改变要么不变要么变大,因为你把大的放前面去了。因为交换不相邻情况也是类似,相当于冒泡的交换过程,就是j和j-1交换,j-1再和j-2交换,以此类推直到i+1与i交换,所以这些交换的情况下都不可能产生比升序还要大的答案,故,升序是最小的情况。我们只用对左和右的乘积排序,然后扫一遍最大值即可。
AC代码:
#include <bits/stdc++.h> using namespace std; struct BIG_INT{ int num[5005];//每个位的数字,从0到n对应个十百千万十万百万千万亿...... int _size; BIG_INT(){ memset(num, 0, sizeof(num)); _size = 0; } int size(){ return _size; } BIG_INT friend operator * (BIG_INT a, BIG_INT b) { BIG_INT c; for(int i = 0; i < a.size(); i++) { int up = 0; for(int j = 0; j < b.size(); j++) { int temp = c.num[i + j] + a.num[i] * b.num[j] + up; up = temp / 10; c.num[i + j] = (temp % 10); } if(up != 0) c.num[i + b.size()] = up; } for(int i = a.size() + b.size(); i >= 0; i--) { if(c.num[i] != 0) { c._size = i + 1; break; } } return c; } BIG_INT friend operator / (BIG_INT a, int b) { BIG_INT c; int r = 0;//余数 for(int i = a.size(); i >= 0; i--) { int temp = r * 10 + a.num[i]; c.num[i] = temp / b; r = temp % b; } for(int i = a.size(); i >= 0; i--) { if(c.num[i] != 0) { c._size = i + 1; break; } } return c; } BIG_INT operator = (int temp) { char t[1005]; sprintf(t, "%d", temp); int size = strlen(t); _size = size; for(int i = 0; i < size; i++) { num[size - i - 1] = t[i] - '0'; } } void output(){ for(int i = _size - 1; i >= 0; i--) printf("%d", num[i]); printf("\n"); } bool friend operator < (BIG_INT a, BIG_INT b){ if(a.size() > b.size()) return false; else if(a.size() < b.size()) return true; else { for(int i = a.size() - 1; i >= 0; i--) { if(a.num[i] != b.num[i]) return a.num[i] < b.num[i]; } return false; } } }; struct Node{ int l, r; int sum; bool friend operator < (Node x, Node y){ return x.sum < y.sum; } }; Node p[10005]; int main() { int n; BIG_INT sum, now, maxn; sum.num[0] = 1; sum._size = 1; scanf("%d", &n); for(int i = 0; i <= n; i++) { scanf("%d%d", &p[i].l, &p[i].r); p[i].sum = p[i].l * p[i].r; } sort(p + 1, p + n + 1); for(int i = 1; i <= n; i++) { now = p[i - 1].l; sum = sum * now; if(maxn < (sum / p[i].r)) maxn = sum / p[i].r; } maxn.output(); return 0; }