P1080 [NOIP2012 提高组] 国王游戏

17 篇文章 0 订阅

题目描述

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

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

输入格式

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

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

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

输出格式

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

输入输出样例

输入

3
1 1
2 3
7 4
4 6

输出

2

说明/提示

【输入输出样例说明】

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

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

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

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

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

按3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。

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

【数据范围】

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

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

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

对于 60%的数据,保证答案不超过 1 0 9 10^9 109

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

贪心,算法,按照左右手乘积最大排队,这样才是能是最大值最小的。
证明:

P1080 [NOIP2012 提高组] 国王游戏 题解

但是数据太大要高精度运算
我、这里写的没有高精度,只能过一半

为什么需要高精度呢?

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,我们可以将这个数字拆开,拆成一位一位的,或者是几位几位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。

对于这类问题,不要指望long double这些东西了,基本数据类型不可能存的下。我们可以把这两个数当成字符串输入到数组中,然后模拟手动的竖式运算(不会的话,回去上小学)得出结果。

说白了,高精度计算就是解决long long也解决不了的问题。
C++高精度

C/C++高精度运算(大整数运算)详解(含压位)

#include<iostream>
#include<algorithm>
using namespace std;
struct people{
    int left;
    int right;
}P[1001];
int kingleft,kingright;
// 排序,这样拍是能出最大值最小的
bool cmp(people a, people b)
{
    return a.right*a.right<b.right*b.left;//升序
}
int main()
{
    int n;
    long long left,ans=-1,temp;
    cin>>n;
    cin>>kingleft>>kingright;
    for(int i=0;i<n;i++)
        cin>>P[i].left>>P[i].right;
    sort(P,P+n,cmp);
    left=kingleft;
    // 计算这样排序后的队列最值,
    for(int i=0;i<n;i++)
    {
        // 每个人应得得钱
        temp=left/P[i].right;
        // 刷新最值
        if(temp>ans)
            ans=temp;
        // 叠乘
        left*=P[i].left;
    }
    cout<<ans;
    return 0;
}

python自带高精度

N=int(input())
#输入国王左右手
s=input().split()
#国王左手
S=int(s[0])
#国王右手
T=int(s[1])
a=[]
#输入各个大臣
for i in range(1,N+1):
    k=input().split()
    a.append((int(k[0]),int(k[1])))
#排序
a.sort(key=lambda x:x[0]*x[1])
ans=0
for i in range(0,N):
    # //表示向下取整
    if(S//(a[i])[1]>ans):
        ans=S//(a[i])[1]
    S*=(a[i])[0]
print(ans)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值