noip2012 国王游戏
描述
恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
格式
输入格式
第一行包含一个整数n,表示大臣的人数。
第二行包含两个整数a和b,之间用一个空格隔开,分别表示国王左手和右手上的整数。接下来n行,每行包含两个整数a和b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
数据
对于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。
--------------------------------------------------------------------------------
正解= 贪心+高精.
贪心证明 :
设存在 相邻大臣A(l1,r1),B(l2,r2),A,B前左手乘积为Sum :
当A在B前时:
则Ans=max(Sum/r1,Sum*l1/r2) ;
当B在A前时:
则Ans=max(Sum/r2,Sum*l2/r1) ;
显然 Sum*l2/r1>Sum/r1 ;
Sum*l1/r2>Sum/r2 ;
所以当 Sum*l2/r1>Sum*l1/r2
即 l2*r2>l1*r1 时 A应在B前
同理
即 l2*r2<l1*r1 时 B应在A前
所以按 l*r 从小到大排序在进行模拟即为正解.
代码如下:
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<string> 5 #include<iostream> 6 #include<queue> 7 #define INF 99999999 8 #define LL long long 9 //using namespace std; 10 struct STR{ 11 int s[3000]; 12 }ans,sum; 13 struct P{ 14 int l,r; 15 }p[1001]; 16 int n; 17 bool cmp(const P &x,const P &y){ 18 return x.l*x.r<y.l*y.r; 19 } 20 void time(STR &a,int b){ 21 int L=a.s[0]; 22 for(int i=1;i<=L;i++) a.s[i]*=b; 23 for(int i=1;i<=L;i++){ 24 a.s[i+1]+=a.s[i]/10000; 25 a.s[i]%=10000; 26 } 27 while(a.s[L+1]){ 28 ++L; 29 a.s[L+1]+=a.s[L]/10000; 30 a.s[L]%=10000; 31 } 32 a.s[0]=L; 33 } 34 void Max(STR &a,STR b){ 35 if(a.s[0]<b.s[0]) { a=b; return ;} 36 if(a.s[0]>b.s[0]) return ; 37 for(int i=a.s[0];i;i--){ 38 if(a.s[i]<b.s[i]) { a=b; return ;} 39 if(a.s[i]>b.s[i]) return ; 40 } 41 } 42 STR div(STR a,int b){ 43 int x=0,L=a.s[0]; 44 STR c; 45 memset(c.s,0,sizeof(c.s)); 46 for(int i=L;i>=1;i--){ 47 x=x*10000+a.s[i]; 48 c.s[i]=x/b; 49 x%=b; 50 } 51 while(!c.s[L]) --L; 52 c.s[0]=L; 53 return c; 54 } 55 void put(STR a){ 56 printf("%d",a.s[a.s[0]]); 57 for(int i=a.s[0]-1;i;i--) printf("%4.4d",a.s[i]); 58 } 59 int main(){ 60 freopen("xx.in","r",stdin); 61 freopen("xx.out","w",stdout); 62 scanf("%d",&n); 63 for(int i=0;i<=n;i++) scanf("%d%d",&p[i].l,&p[i].r); 64 std :: sort(p+1,p+1+n,cmp); 65 sum.s[0]=sum.s[1]=1; 66 time(sum,p[0].l); 67 for(int i=1;i<=n;i++){ 68 Max(ans,div(sum,p[i].r)); 69 time(sum,p[i].l); 70 } 71 put(ans); 72 }