P1080 国王游戏

题目描述

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

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

输入输出格式

输入格式:

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

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

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

输出格式:

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

输入输出样例

输入样例#1:

3
1 1
2 3
7 4
4 6

输出样例#1:

2

说明

【输入输出样例说明】

按11、22、33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按 11、33、22 这样排列队伍,获得奖赏最多的大臣所获得金币数为22;

按 22、11、33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按22、33、11这样排列队伍,获得奖赏最多的大臣所获得金币数为99;

按 33、11、22这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按33、22、11 这样排列队伍,获得奖赏最多的大臣所获得金币数为 99。

因此,奖赏最多的大臣最少获得 22个金币,答案输出 22。

【数据范围】

对于 20%的数据,有 1≤ n≤ 10,0 < a,b < 81≤n≤10,0<a,b<8;

对于 40%的数据,有1≤ n≤20,0 < a,b < 81≤n≤20,0<a,b<8;

对于 60%的数据,有 1≤ n≤1001≤n≤100;

对于 60%的数据,保证答案不超过 10^9109;

对于 100%的数据,有 1 ≤ n ≤1,000,0 < a,b < 100001≤n≤1,000,0<a,b<10000。

NOIP 2012 提高组 第一天 第二题


思路

我们假设一个正确的序列中有两个元素 i 与 i + 1,他们左右手的数字分别为Ai,Bi,Ai+1,Bi+1

排在i大臣前面的所有人的左手上的数的乘积为T(以下向下取整省略不写)

这两位大臣得到最多的硬币为 max( T / Bi, (T * Ai) / Bi+1 ) = Ans1

假设交换这两位大臣 则他们得到最多硬币数变为 max( T / Bi+1, (T * Ai+1) / Bi ) = Ans2

要求Ans1 <= Ans2,原序列顺序可能不是最优(否则这两位大臣交换能得到更有策略)

所以要使 T / Bi 和 (T * Ai) / Bi+1都小于等于Ans2即可满足要求

由于T / Bi <= (T * Ai+1) / Bi ,T / Bi 肯定能满足要求,只要使 ( T * Ai ) / Bi+1 也小于等于 Ans2即可

(T * Ai) / Bi+1 肯定大于等于 T / Bi+1 ,所以只能使 (T * Ai+1) / Bi 大于等于(T * Ai) / Bi+1 ,否则不能达到要求

然后我们就可以列出不等式 (T * Ai) / Bi+1 <= (T * Ai+1) / Bi

因为T是正数,所以可以同时消去

Ai / Bi+1 <= Ai+1 / Bi

同乘Bi+1Bi

Ai * Bi <= Ai+1 * Bi+1

所以,只要按Ai * Bi从小到大排序就不成问题了。(当然别把国王也排序了)

注意要加高精度。

代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10005 struct ppp{
int a, b;
}p[MAXN]; int n; bool cmp( ppp x, ppp y ){
return x.a * x.b < y.a * y.b;
} int s[4005], len;
int ans[4005], ans_l(0); void Mul( int x ){
int t(len);
for ( int i = 1; i <= len; ++i ) s[i] *= x;
for ( int i = 1; i <= len + 5; ++i ){
if ( s[i] ) t = i;
s[i + 1] += s[i] / 10;
s[i] %= 10;
}
len = t;
} void Copy( int c[], int c_l ){
for ( int i = 1; i <= c_l; ++i ) ans[i] = c[i];
ans_l = c_l;
} void Out( int s[], int l ){
for ( int i = l; i >= 1; --i ) printf( "%d", s[i] );
putchar('\n');
}
void Div( int x ){
int c[4005], l(-1);
for ( int i = 1; i <= len; ++i ) c[i] = s[i];
for ( int i = len; i >= 1; --i ){
c[i - 1] += ( c[i] % x ) * 10;
c[i] /= x;
if ( c[i] && l == -1 ) l = i;
}
if ( ans_l == l ){
bool flg(0);
for ( int i = l; i >= 1; --i )
if ( ans[i] < c[i] ){ flg = 1; break; }
else break;
if ( flg ) Copy( c, l );
}
if ( ans_l < l ) Copy( c, l );
} int main(){
scanf( "%d", &n );
scanf( "%d%d", &p[0].a, &p[0].b );
for ( int i = 1; i <= n; ++i ) scanf( "%d%d", &p[i].a, &p[i].b );
sort( p + 1, p + n + 1, cmp );
s[1] = 1; len = 1;
Mul( p[0].a );
for ( int i = 1; i <= n; ++i )
Div( p[i].b ), Mul( p[i].a );
Out( ans, ans_l );
return 0;
}

完事!!!

最新文章

  1. 数据结构看书笔记(二)--算法(Algorithm)简介
  2. NSURLErrorDomain -999 &quot;Canceled&quot; 错误探究
  3. ORA-00030: User session ID does not exist.
  4. 网站移植到linux上后常犯的错误
  5. 0511 backlog
  6. handler 异步执行(进度条加载到100)
  7. 记在thinkPHP中一个创建模型的小错误
  8. hexo 搭建博客
  9. Codeforces 424 B Megacity【贪心】
  10. win7 下恢复“经典任务栏”/“快速启动栏”,关闭“窗口自动最大化” -摘自网络
  11. rand(7) 到rand(10)
  12. jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
  13. xcode 5与ios 7的屏幕适配问题
  14. CSS自学笔记(2):CSS语法
  15. UISearchBar的扩展使用
  16. node 全局对象global —— 记录在线人员
  17. Schlumberger Petrel 2016.3 地震解释 油藏模拟
  18. minifilter
  19. mysql里几个超时配置参数wait_timeout,net_read_timeout等
  20. transition(过渡)

热门文章

  1. @bzoj - 3836@ [Poi2014]Tourism
  2. PHP 手机短信验证码 laravel 实现流程
  3. python selenium 获取对象输入的属性值
  4. centos安装hdp
  5. 给tomcat容器配置SSL的记录,包含项目完整部署过程
  6. jieba分词流程及部分源码解读(一)
  7. hdu 1358 Period (KMP求循环次数)
  8. Spring Boot Thymeleaf 使用详解
  9. SVN提示update更新成功,但是本地文件却没有更新
  10. PhpStorm terminal无法输入命令的解决方法