题目描述
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入输出格式
输入格式:
第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式:
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
输入输出样例
输入样例#1: 复制
3
1 1
2 3
7 4
4 6
输出样例#1: 复制
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,0 < a、b < 8;
对于 40%的数据,有 1≤ n≤20,0 < a、b < 8;
对于 60%的数据,有 1≤ n≤100;
对于 60%的数据,保证答案不超过 10^9;
对于 100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10000。
NOIP 2012 提高组 第一天 第二题
贪心。话说我觉得今年noip会有一道贪心的题。多刷一些贪心。
贪心,一旦证明了是贪心的思想,就很好写。关键是证明局部最优一定会达到全局最优
首先明确相邻的两个大臣交换位置,只会对他们两个人造成影响,而不会影响到前面或后面的人、
那么假设现在已经排了i-1个大臣,p=a[1]* a[2] * a[3] * ……* a[i-1];
若i大臣在i+1大臣的前面
第i个大臣的钱w[i]=p/b[i],
第i+1个大臣的钱w[i+1]=p*a[i]/b[i+1]
若i+1大臣在i大臣前面
第i个大臣的钱w[i]=p*a[i+1]/b[i],
第i+1个大臣的钱w[i+1]=p/b[i+1];
显然p* a[i+1]/b[i]>p/b[i] && p*a[i]/b[i+1]>p/b[i+1]
所以两个里面的最大值在p* a[i+1]/b[i] 和 p*a[i]/b[i+1] 之间
若p*a[i+1]/b[i] > p*a[i]/b[i+1](这样就是i+1大臣排在i后面最大值会更小) 则 a[i+1]*b[i+1]>a[i]*b[i]
所以如果要让大臣得到的钱的最大值最小就要保证两个相邻的大臣,前面的左手 * 右手<后面的左手 * 右手。所以按照a*b从小到大排序
注意要用高精度。
数组开小了白丢30分!noip丢这样的分可真是太可惜了。
一周后的noip中,数组在保证不MLE的前提下不妨开的大一点以防万一。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,sum,a[10001],s[10001];
struct st{
int len,a[10001];
};
struct Chen{
int a,b;
}chen[10001];
st ans;
int read()
{
int now=0,f=1; char ch=getchar();
while (ch<'0'||ch>9) {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9')
{
now=(now<<1)+(now<<3)+ch-'0';
ch=getchar();
}
return now*f;
}
bool comp(Chen a,Chen b) {return a.a*a.b<b.a*b.b;}
bool ifbig(st a,st b)
{
if (a.len!=b.len) return a.len>b.len?true:false;
int i=a.len;
while (a.a[i]==b.a[i]) i--;
return a.a[i]>b.a[i]?true:false;
}
void shuchu(st a)
{
for (int i=a.len; i>=1; i--)
printf("%d",a.a[i]);
printf("\n");
}
st mul(st a,st b)
{
st c;
memset(c.a,0,sizeof(c.a));
c.len=a.len+b.len-1;
for (int i=1; i<=a.len; i++)
for (int j=1; j<=b.len; j++)
c.a[i+j-1]+=a.a[i]*b.a[j];//又是i j不分
for (int i=1; i<=c.len; i++)
if (c.a[i]>=10)
{
c.a[i+1]+=c.a[i]/10;
c.a[i]%=10;
}
while (c.a[++c.len])
{
c.a[c.len+1]+=c.a[c.len]/10;
c.a[c.len]%=10;
}
while (!c.a[c.len]&&c.len>=2) c.len--;
return c;
}
st dev(st a,int b)
{
st c; memset(c.a,0,sizeof(c.a));
c.len=a.len;
for (int i=c.len; i>=1; i--)
{
c.a[i]+=a.a[i]/b;
a.a[i-1]+=10*(a.a[i]%b);
}
while (!c.a[c.len]&&c.len>=2) c.len--;
return c;
}
st zhuanhua(int x)
{
st c; c.len=0; memset(c.a,0,sizeof(c.a));
while (x)
{
c.a[++c.len]=x%10;
x/=10;
}
return c;
}
void work()
{
st Sum; Sum.len=1; memset(Sum.a,0,sizeof(Sum.a)); Sum.a[1]=1;
st tmp; tmp.len=0; memset(tmp.a,0,sizeof(tmp.a));
for (int i=1; i<=n; i++)
{
st a=zhuanhua(chen[i-1].a);
Sum=mul(Sum,a);
tmp=dev(Sum,chen[i].b);
if (ifbig(tmp,ans)) ans=tmp;
}
}
int main()
{
/* st tmp=zhuanhua(1000);
if (ifbig(tmp,ans)) ans=tmp; shuchu(ans); return 0;*/
scanf("%d",&n);
for (int i=0; i<=n; i++)
scanf("%d%d",&chen[i].a,&chen[i].b);
// ans.len=1e5;
sort(chen+1,chen+1+n,comp);
ans.len=0;
work();
shuchu(ans);
return 0;
}