【NOIP 2012 国王游戏】 贪心+高精度

题目描述

恰逢 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 提高组 第一天 第二题

 

我要直接搬运证明了。。

按照a*b排序,然后计算,计算那里要高精度。

 

国王游戏

将左手与右手的乘积从小到大排序,然后计算求最大值即可。(需要高精度)

证明:

1)知道,如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人

2)假设相邻的两个人i, i + 1。设A[i] B[i] <= A[i + 1] B[i + 1],i之前所有人的左手乘积为S。

则,ans1 = max{S / B[i], S * A[i] / B[i + 1]}

若交换

则,ans2 = max{S / B[i + 1], S * A[i + 1] / B[i]}

因为,A[i] B[i] <= A[i + 1] B[i + 1]

所以,S A[i] / B[i + 1] <= S A[i + 1] / B[i]

又因为,S / B[i + 1] <= S * A[i] / B[i + 1]

所以,ans2 = S * A[i + 1] / B[i]

ans1 = max{S / B[i], S * A[i] / B[i + 1]}

所以,ans1 <= ans2

证毕 至于高精度:

由题意知,0 < a,b < 10000,所以用10000进制的高精度进行运算就可以了

转自 新浪博客

链接

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 using namespace std;
 9 #define Maxn 1010
10 
11 struct node
12 {
13     int a,b;
14 }t[Maxn];
15 
16 bool cmp(node x,node y) {return x.a*x.b<y.a*y.b;}
17 
18 struct bint
19 {
20     int w[30010],l;
21 };
22 bint now,mx,C;
23 
24 void mul(int x)
25 {
26     for(int i=1;i<=now.l;i++) now.w[i]*=x;
27     for(int i=1;i<=now.l;i++)
28     {
29         now.w[i+1]+=now.w[i]/10;
30         now.w[i]%=10;
31     }
32     while(now.w[now.l+1]!=0)
33     {
34         now.w[now.l+2]+=now.w[now.l+1]/10;
35         now.w[now.l+1]%=10;
36         now.l++;
37     }
38 }
39 
40 void get_C(int x)
41 {
42     int y=0;
43     C.l=now.l;
44     memset(C.w,0,sizeof(C.w));
45     for(int i=now.l;i>=1;i--)
46     {
47         y=y*10+now.w[i];
48         if(y>=x)
49         {
50             C.w[i]=y/x;
51             y%=x;
52         }
53     }
54     while(C.w[C.l]==0&&C.l>1) C.l--;
55 }
56 
57 void change()
58 {
59     mx.l=C.l;
60     for(int i=1;i<=C.l;i++) mx.w[i]=C.w[i];
61 }
62 
63 void get_mx()
64 {
65     if(C.l<mx.l) return;
66     else if(C.l>mx.l) change();
67     else
68     {
69         for(int i=C.l;i>=1;i--)
70         {
71             if(C.w[i]<mx.w[i]) return;
72             if(C.w[i]>mx.w[i]) {change();return;}
73         }
74     }
75 }
76 
77 int main()
78 {
79     int n;
80     scanf("%d",&n);
81     int A,B;
82     scanf("%d%d",&A,&B);
83     for(int i=1;i<=n;i++) scanf("%d%d",&t[i].a,&t[i].b);
84     sort(t+1,t+1+n,cmp);
85     now.l=1;memset(now.w,0,sizeof(now.w));
86     now.w[1]=1;
87     mx.l=1,mx.w[1]=0;
88     
89     mul(A);
90     for(int i=1;i<=n;i++)
91     {
92         get_C(t[i].b);
93         get_mx();
94         mul(t[i].a);
95     }
96     for(int i=mx.l;i>=1;i--) printf("%d",mx.w[i]);
97     printf("
");
98     return 0;
99 }
View Code

2016-11-16 10:32:55

原文地址:https://www.cnblogs.com/Konjakmoyu/p/6068498.html