【NOIP2012】国王游戏

本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1080


这道题用到了贪心的思想,与简单的贪心不同,最优解并不能一眼就看出来,需要通过列式比较。我们设想对于任意的两位大臣x和y,他们两个的排列顺序会对答案有影响。假设国王和之前的大臣左手上的数乘积为pre,若x排在y前,ans1=max(pre/x.b,pre*x.a/y.b),ans2=max(pre/y.b,pre*y.a/x.b)。因为必有pre*x.a/y.b>pre/y.b,pre*y.a/x.b>pre/x.b,若要ans1<ans2,则pre*x.a/y.b<pre*y.a/x.b,否则pre*x.a/y.b将会成为最大的数,也就是ans1大于ans2,而我们最终希望答案越小越好,所以就按a*b作为优先级将大臣们排序,最终可以使得获得奖赏最多的大臣所获金币数最小。这是本题的关键,也是一种非常重要的贪心思想,在那道烹调方案中,就要用到。

有了以上分析就可以有60分,但本题ans的最大值可以达到10^5000左右!!!要用高精度,这才是最坑的。弄了好久才过去,借着这个契机,好好改改我的高精度模板。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<string>
 5 using namespace std;
 6 const int maxn=1005,maxl=5005;
 7 int n,ka,kb;
 8 struct BigInteger {
 9     int num[maxl],len;
10     BigInteger(int x=0) {
11         memset(num,0,sizeof(num));
12         num[1]=x;len=1;
13     }
14     bool operator < (const BigInteger& rhs) const {
15         if(len==rhs.len) { //小于运算符可将其他比较运算符表示出来
16             for(int i=len;i>=1;--i)
17                 if(num[i]!=rhs.num[i]) return num[i]<rhs.num[i];
18             return false;
19         }
20         else return len<rhs.len;
21     }
22      void operator * (const int& rhs) { //高精乘低精
23         for(int i=1;i<=len;++i) num[i]*=rhs; //先每位乘上再处理进位
24         for(int i=1;i<=len;++i)
25             for(int j=i;num[j]>9;++j) {
26                 num[j+1]+=num[j]/10;
27                 num[j]%=10;
28             }
29         len+=15;
30         while(!num[len]&&len>1) --len;
31     }
32     BigInteger operator / (const int& rhs) const {
33         BigInteger ans=*this;
34         for(int i=ans.len;i>=1;--i) {
35             ans.num[i-1]+=ans.num[i]%rhs*10;
36             ans.num[i]/=rhs;
37         }
38         while(!ans.num[ans.len]&&ans.len>1) --ans.len;
39         return ans;
40     }
41     void print() {
42         for(int i=len;i>=1;--i) printf("%d",num[i]);
43     }
44 } now,ans;
45 struct minister {
46     int a,b;
47     bool operator < (const minister& rhs) const {
48         return a*b<rhs.a*rhs.b;
49     }
50 } M[maxn];
51 int main() {
52     scanf("%d%d%d",&n,&ka,&kb);
53     for(int i=1;i<=n;++i) scanf("%d%d",&M[i].a,&M[i].b);
54     sort(M+1,M+n+1);
55     now=BigInteger(1);now*ka;
56     for(int i=1;i<=n;++i) {
57         if(ans<now/M[i].b) ans=now/M[i].b;
58         now*M[i].a;
59     }
60     ans.print();
61     return 0;
62 }
AC代码
原文地址:https://www.cnblogs.com/Mr94Kevin/p/9626770.html