题目描述
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
思路
问题是怎么排序使得最大权值最小,那我们就需要知道排序的条件,为了找出这个条件,我们考虑第i个人和第i+1个人。
解:设a,b为第i个人左右手的数字,c,d为第i+1个人左右手的数字,s为第1个人到第i-1个人左手数字的乘积
可以得出第i个人的权值为wi = s / b 第i+1个人的权值为 wi+1 = s * a / d,那么最大值为max (s / b, s * a / d)
可以得出换了位置之后第i+1个人的权值为 wi+1 = s / d 第i个人的权值为 wi = s * c / b,那么最大值为max (s / d, s * c / b)
假设换了位置更优 那么 max (s / d, s * c / b) < max (s / b, s * a / d)
假设s / d > s * c / b 那么 s / d < max (s / b, s * a / d),很显然的是s*a/d>s/d,那么根据s / b > s / d 可以得出d > b 但与条件(b>c*d)矛盾不成立
假设s/d
代码
注意了,这个代码在codevs上只有60分。我不知道为什么,他给个正确答案是
2166489661101032350678866897536628698296804147316726878162441737980268621335310233327258927458239967674879428851028800069063620140885606400000000000000000
这么大个数是什么意思???
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
const int N=1000+7;
long long n,lf,rg,sum,maxn=0;
struct node
{
long long L,R;
}people[N];
int max(long long x,long long y)
{
if (x>=y) return x;
else return y;
}
bool cmp(node a,node b)
{
return a.L*a.R<b.L*b.R;
}
int main()
{
scanf("%lld%lld%lld",&n,&lf,&rg);
for (int i=1;i<=n;i++)
scanf("%lld%lld",&people[i].L,&people[i].R);
sort(people+1,people+1+n,cmp);
sum=lf;
for (int i=1;i<=n;i++)
{
maxn=max(maxn,sum/people[i].R);
sum=sum*people[i].L;
}
printf("%lld\n",maxn);
return 0;
}
可能是写不出来这个高精度吧