题目描述
恰逢 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%的数据,保证答案不超过 109;
对于 100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10000。
NOIP 2012 提高组 第一天 第二题
贪心策略 :左右手乘积最小排在前
证:x1 y1
x2 y2
... ...
-----------
xa ya
xb yb
----------
... ...
按 (xi*yi) 从小到大排序
在xa之前的乘积是一定的 我们假设为 S
xa,ya 和xb,yb交换前
xa 获得的金币 为(S/ya) 记为 X
xb 获得的金币 为((S*xa)/yb) 记为 Y
xa,ya 和xb,yb交换后
xa 获得的金币 为(S/yb) 记为 P
xb 获得的金币 为((S*xb)/ya) 记为 Q
结果是找 max(X,Y) 和max(P,Q)之中小的那个数
两个max同乘yayb之后
X 为(S*yb) Y为 (S*xa*ya)
P 为(S*ya) Q为 (S*xb*yb)
由于要让最大值尽量小 那么
如果yb大于xa*ya 那么结果取S*yb
而 xb*yb一定大于xa*ya
所以我们可以得出 xi*yi 最小时策略最优
1 /* 2 一道贪心+高精 3 贪心策略简单 就是找左右手乘积最小的排在前边 4 高精恶心 我不想再见这道题第二次 5 */ 6 #include<cstdio> 7 #include<cstring> 8 #include<iostream> 9 #include<algorithm> 10 #define MAXN 5010 11 #define LL long long 12 13 using namespace std; 14 15 struct node { 16 int a,b; 17 LL sum; 18 }; 19 node e[MAXN]; 20 21 int ans[MAXN],ans1[MAXN],b[MAXN]; 22 23 int n,p; 24 25 char s[MAXN]; 26 27 inline void read(int &x) { 28 int f=1;x=0;char c=getchar(); 29 while(c>‘9‘||c<‘0‘) {if(c==‘-‘) f=-1;c=getchar();} 30 while(c>=‘0‘&&c<=‘9‘) {x=(x<<1)+(x<<3)+c-48;c=getchar();} 31 x=x*f; 32 } 33 34 inline bool cmp(const node x,const node y) { 35 return x.sum<y.sum; 36 } 37 38 inline void chu(int x) { 39 b[0]=0; 40 memset(b,0,sizeof b); 41 LL k=0; 42 for(int i=ans1[0];i>=1;i--) { 43 k=k*10+ans1[i]; 44 if(k>=x) { 45 if(b[0]==0) b[0]=i; 46 b[i]=k/x; 47 k%=x; 48 } 49 } 50 } 51 52 inline void compare() { 53 if(b[0]>ans[0]) { 54 for(int i=0;i<=MAXN;i++) ans[i]=b[i]; 55 return; 56 } 57 else if(b[0]==ans[0]) { 58 for(int i=ans[0];i>=1;i--) { 59 if(b[i]>ans[i]) { 60 for(int j=0;j<=MAXN;j++) ans[j]=b[j]; 61 return; 62 } 63 } 64 } 65 } 66 67 inline void mul(int x) { 68 LL k=0; 69 memset(b,0,sizeof b); 70 for(int i=1;i<=ans1[0];i++) { 71 b[i]+=ans1[i]*x+k; 72 b[i+1]+=b[i]/10; 73 b[i]=b[i]%10; 74 } 75 for(b[0]=ans1[0];b[b[0]+1];) { 76 b[++b[0]+1]+=b[b[0]]/10; 77 b[b[0]]=b[b[0]]%10; 78 } 79 for(int i=0;i<MAXN;i++) ans1[i]=b[i]; 80 } 81 82 int main() { 83 read(n); 84 scanf("%s",s+1); 85 for(int i=strlen(s+1);i>=1;i--) ans1[++ans1[0]]=s[i]-‘0‘; 86 read(p); 87 for(int i=1;i<=n;i++) { 88 read(e[i].a); 89 read(e[i].b); 90 e[i].sum=e[i].a*e[i].b; 91 } 92 sort(e+1,e+1+n,cmp); 93 for(int i=1;i<=n;i++) { 94 chu(e[i].b); 95 compare(); 96 mul(e[i].a); 97 } 98 for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); 99 printf("\n"); 100 return 0; 101 }
代码