Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)

Description

恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

Input

第一行包含一个整数 n,表示大臣的人数。

第二行包含两个整数a和b,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来n行,每行包含两个整数a和b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

Output

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

Sample Input

3

1 1

2 3

7 4

4 6

Sample Output

2

Http

Luogu:https://www.luogu.org/problem/show?pid=1080

Source

贪心,高精度

题目大意

给出若干组二元组(a,b),对于一种排列方式,定义第i个二元组的花费为前面所有人的a之积除以第i个的b。现在要求求一种排列方式,使得其中最大的花费最小。

解决思路

我们来考虑排序方式。对于\(\forall\)两个人\(A,B\),设\(A\)的左手为\(A_l\),右手为\(A_r\),\(B\)同理。现在假设\(A与B\)是相邻的,他们前面的所有人的左手乘积为\(P\)。则有

顺序 A的花费 B的花费
A在前 \(\frac{T}{A_r}\) \(\frac{T*A_l}{B_r}\)
B在前 \(\frac{T*B_l}{A_r}\) \(\frac{T}{B_r}\)

那么我们如何排列\(A和B\)呢?那一定取决于上面表格中的两行中的最大值。而因为所有的数都是整数,所以我们可以知道\(\frac{T}{A_r}\)与\(\frac{T}{B_r}\)是不可能成为最大值的。

所以我们考虑\(\frac{T*A_l}{B_r}\)和\(\frac{T*B_l}{A_r}\)。

当\(\frac{T*A_l}{B_r} > \frac{T*B_l}{A_r}\)时,经过恒等变换,我们可以得到\(A_l*A_r>B_l*B_r\)也就是说,当A的左右手乘积大于B的左右手乘积时,我们把B排在前面会更优。

那么\(\frac{T*A_l}{B_r} < \frac{T*B_l}{A_r}\)是否也满足呢?我们发现是满足的。

也就是说,最优的排列方式为将人按照左右手乘积升序排序。至于求解其中的最大值,只要从1开始做一遍就可以啦。

最后需要注意的是,本题需要高精度。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. using namespace std;
  7. #define mem(Arr,x) memset(Arr,x,sizeof(Arr))
  8. const int maxN=2000;
  9. const int maxNum=5000;
  10. const int inf=2147483647;
  11. #define ll long long
  12. class People//定义一个关于人的结构体,方便按照左右手乘积排序
  13. {
  14. public:
  15. ll l,r;
  16. };
  17. bool operator < (People A,People B)//定义比较
  18. {
  19. return A.l*A.r<B.l*B.r;
  20. }
  21. class BigInteger//定义高精度
  22. {
  23. public:
  24. int siz;
  25. ll Num[maxNum];
  26. BigInteger();
  27. BigInteger(int x);
  28. BigInteger(ll x);
  29. void operator = (int B);
  30. bool operator == (int B);
  31. bool operator == (BigInteger B);
  32. BigInteger operator + (BigInteger B);
  33. BigInteger operator * (ll B);
  34. BigInteger operator / (ll B);
  35. };
  36. ostream& operator << (ostream & os,BigInteger A)//重载输出运算符方便输出
  37. {
  38. if (A.siz==0)
  39. {
  40. os<<0;
  41. return os;
  42. }
  43. for (int i=A.siz;i>=1;i--)
  44. os<<A.Num[i];
  45. return os;
  46. }
  47. bool operator < (BigInteger A,BigInteger B)//重载小于运算符
  48. {
  49. if (A.siz<B.siz)
  50. return 1;
  51. if (A.siz>B.siz)
  52. return 0;
  53. for (int ii=A.siz;ii>=1;ii--)
  54. {
  55. if (A.Num[ii]>B.Num[ii])
  56. return 0;
  57. if (A.Num[ii]<B.Num[ii])
  58. return 1;
  59. }
  60. }
  61. ll n;
  62. People P[maxN];
  63. ll read();
  64. int main()//主程序
  65. {
  66. n=read();
  67. P[0].l=read();
  68. P[0].r=read();
  69. for (int i=1;i<=n;i++)
  70. {
  71. P[i].l=read();
  72. P[i].r=read();
  73. }
  74. sort(&P[1],&P[n+1]);//将人排序
  75. BigInteger ret=P[0].l;//ret即前面所有人左手的乘积
  76. BigInteger Ans=0;//Ans记录最大的
  77. for (int i=1;i<=n;i++)//依次计算
  78. {
  79. Ans=max(Ans,ret/P[i].r);
  80. ret=ret*P[i].l;
  81. }
  82. cout<<Ans<<endl;
  83. return 0;
  84. }
  85. ll read()
  86. {
  87. ll x=0;
  88. char ch=getchar();
  89. while ((ch<'0')||(ch>'9'))
  90. ch=getchar();
  91. while ((ch>='0')&&(ch<='9'))
  92. {
  93. x=x*10+ch-48;
  94. ch=getchar();
  95. }
  96. return x;
  97. }
  98. //以下就是高精度的重载
  99. BigInteger::BigInteger()
  100. {
  101. siz=0;
  102. mem(Num,0);
  103. }
  104. BigInteger::BigInteger(int B)
  105. {
  106. siz=0;
  107. mem(Num,0);
  108. while (B!=0)
  109. {
  110. siz++;
  111. Num[siz]=B%10;
  112. B=B/10;
  113. }
  114. }
  115. BigInteger::BigInteger(ll B)
  116. {
  117. siz=0;
  118. mem(Num,0);
  119. while (B!=0)
  120. {
  121. siz++;
  122. Num[siz]=B%10;
  123. B=B/10;
  124. }
  125. }
  126. void BigInteger::operator = (int B)
  127. {
  128. siz=0;
  129. mem(Num,0);
  130. while (B!=0)
  131. {
  132. siz++;
  133. Num[siz]=B%10;
  134. B=B/10;
  135. }
  136. }
  137. bool BigInteger::operator == (BigInteger B)
  138. {
  139. if (siz!=B.siz)
  140. return 0;
  141. for (int ii=1;ii<=siz;ii++)
  142. if (Num[ii]!=B.Num[ii])
  143. return 0;
  144. return 1;
  145. }
  146. bool BigInteger::operator == (int B)
  147. {
  148. BigInteger A(B);
  149. if (A==B)
  150. return 1;
  151. return 0;
  152. }
  153. BigInteger BigInteger::operator + (BigInteger B)
  154. {
  155. BigInteger Ans;
  156. Ans.siz=max(siz,B.siz);
  157. for (int ii=1;ii<=Ans.siz;ii++)
  158. Ans.Num[ii]=Num[ii]+B.Num[ii];
  159. for (int ii=1;ii<Ans.siz;ii++)
  160. {
  161. Ans.Num[ii+1]+=Ans.Num[ii]/10;
  162. Ans.Num[ii]%=10;
  163. }
  164. while (Ans.Num[Ans.siz]>=10)
  165. {
  166. Ans.Num[Ans.siz+1]+=Ans.Num[Ans.siz]/10;
  167. Ans.Num[Ans.siz]%=10;
  168. Ans.siz++;
  169. }
  170. return Ans;
  171. }
  172. BigInteger BigInteger::operator * (ll B)
  173. {
  174. BigInteger Ans;
  175. for (int ii=1;ii<=siz;ii++)
  176. Ans.Num[ii]=1ll*Num[ii]*(ll)(B);
  177. Ans.siz=siz;
  178. for (int ii=1;ii<Ans.siz;ii++)
  179. {
  180. Ans.Num[ii+1]+=Ans.Num[ii]/10;
  181. Ans.Num[ii]%=10;
  182. }
  183. while (Ans.Num[Ans.siz]>=10)
  184. {
  185. Ans.Num[Ans.siz+1]+=Ans.Num[Ans.siz]/10;
  186. Ans.Num[Ans.siz]%=10;
  187. Ans.siz++;
  188. }
  189. return Ans;
  190. }
  191. BigInteger BigInteger::operator / (ll B)
  192. {
  193. BigInteger Ans;
  194. int res=0;
  195. for (int ii=siz;ii>=1;ii--)
  196. {
  197. res=res*10+Num[ii];
  198. Ans.Num[ii]=res/B;
  199. res=res%B;
  200. }
  201. Ans.siz=siz;
  202. while (Ans.Num[Ans.siz]==0)
  203. Ans.siz--;
  204. return Ans;
  205. }

Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)的更多相关文章

  1. [noip2012]国王游戏<贪心+高精度>

    题目链接: https://vijos.org/p/1779 https://www.luogu.org/problem/show?pid=1080 http://codevs.cn/problem/ ...

  2. 洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度

    题目:https://www.luogu.org/problemnew/show/P1080 排序方法的确定,只需任取两个人,通过比较与推导,可以得出ai*bi小的人排在前面: 高精度写的时候犯了些细 ...

  3. 【NOIP2012提高组】国王游戏 贪心 + 高精度

    题目分析 题目答案不具有单调性,所以不可以二分,转而思考贪心.因为无法确定位置,所以考虑如何才能让对于每一个$1 ~ i$使得$i$的答案最大,即$1 ~ i$最后一个最优.若设对于位置$i$,$a[ ...

  4. P1080 国王游戏 贪心 高精度

    题目描述 恰逢 HH国国庆,国王邀请nn 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 nn 位大臣排成一排,国王站在队伍的 ...

  5. P1080 【NOIP 2012】 国王游戏[贪心+高精度]

    题目来源:洛谷 题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王 ...

  6. Luogu P1080 [NOIP2012]国王游戏

    题目 按\(a_i*b_i\)升序排序即可. 证明考虑交换法. 对于排序后相邻的两个人\(i,j(a_ib_i\le a_jb_j)\),设前面的总的积为\(s\),则当前答案为\(\max(\fra ...

  7. Luogu P1080国王游戏(贪心)

    国王游戏 题目链接:国王游戏 ps:题目数据说明了要写高精度. 这个题的答案是\(a.l * a.r < b.l * b.r\)按照这个进行排序 题解中大部分只是如何证明排序是: \(a.l * ...

  8. NOIP2012 国王游戏

    2国王游戏 (game.cpp/c/pas) [问题描述] 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数 ...

  9. NOIP2012国王游戏(60分题解)

    题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王站在队伍的最前面 ...

  10. 继续写高精!noip2012国王游戏。。。

    国王游戏 题目描述: 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王 ...

随机推荐

  1. BTrace 初探

    BTrace 是一款java诊断工具,在解决现场问题的时候非常有用. 今天使用的时候碰到几个坑,先记录一下. 下载下来以后直接运行报错 root@iZ2ze89756yjbvq7le6obdZ:~/b ...

  2. 【JVM.6】虚拟机类加载机制

    一.概述 虚拟机类加载机制:虚拟机把描述类的数据从Class文件中加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型. 与那些在编译时需要进行连接工作的语言不同 ...

  3. Python数据类型-7

    什么数据类型. int 1,2,3用于计算. bool:True,False,用户判断. str:存储少量数据,进行操作 'fjdsal' '二哥','`13243','fdshklj' '战三,李四 ...

  4. 读书笔记(chapter7)

    第七章 链接 链接是将各种代码和数据部分收集起来并且组合成为一个单一文件的过程.1.这个文件可被加载到存储器并执行:2.也可以执行于加载时,也就是在程序被加载器加载到存储器并执行:3.甚至可以执行于运 ...

  5. Typecho博客迁移

    在新的机器上先搭建好一个新的Typecho博客,数据库名称和原博客相同(可以省不少事). 备份原来博客的usr目录. 备份mysql数据库,命令: mysqldump -uroot -p --all- ...

  6. [转帖]从 2G 到 5G,手机上网话语权的三次改变

    从 2G 到 5G,手机上网话语权的三次改变 美国第一大电信运营商 Verizon 公司的 CEO Hans Vestberg 手持一部 iPad,屏幕上显示俯瞰地面的飞行地图.400 多公里外的洛杉 ...

  7. [日常工作]GS使用消息队列进行凭证实时记账 提高性能配置方法

    1. 安装消息队列服务 使用平台技术部的一键安装工具,安装. 自带jdk以及activeMQ 自动注册服务. 比较方便. 2. 修改/gsp/config下面的MQ配置文件,将消息队列服务修改为当前虚 ...

  8. js字符串和正则表达式

    字符串的生成转换 你可以将任何类型的数据都转换为字符串,你可以用下面三种方法的任何一种: var myStr = num.toString(); // "19" var myStr ...

  9. 设计模式之工厂模式(c++)

    问题描述 在面向对象系统设计中经常可以遇到以下的两类问题:1)为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口.这样我们可以通过声明 ...

  10. CPK公式

    CP:Cp = (USL-LSL)/6σ  USL上限值.LSL下限值.σ为产品特性值总体标准差: CPK:Cpk=Cp-|M-μ|/3σ  μ为产品特性值的总体均值,σ为产品特性值总体标准差,M為目 ...