[贪心][高精度][NOIP]国王游戏

题目梗概

有n个大臣,他们可以拿到他们之前所有人左手数的乘积除以他的右手,问是否能通过调换位置来使拿钱最多的大臣拿的钱最少。

思考

贪心证明:

设相邻的两个人$i, i + 1$。设$A[i] \times B[i] \leqslant  A[i + 1] B[i + 1]$,i之前所有人的左手乘积为S。

则,$ans1 = max \left (\frac{S}{B[i]} , \frac{S}{A[i] \times B[i+1]}  \right )$

若交换

$ans2 = max \left (\frac{S}{B[i+1]} , \frac{S \times A[i+1]}{B[i]} \right )$

$\because A[i] \times B[i] \leqslant  A[i + 1] B[i + 1]$

$\therefore \frac{S \times A[i]}{B[i+1]} \leqslant  \frac{S \times A[i + 1]}{B[i]}$

$\because \frac{S}{B[i+1]} \leqslant\frac{ S \times A[i] }{ B[i + 1]}$

$\therefore ans2 =\frac{ S \times A[i + 1]}{B[i]} $

$\therefore ans1<=ans2$

代码实现比较烦了,高精度乘,高精度除。折腾了两小时还是没写出来。找了一篇题解,发现自己太傻比。

#include<string>
#include<iostream>
#include<algorithm>
#define STR string   // 搞个笑 方个便
#define LEN length()
#define B begin()
#define E end()
#define tonum(X) for (o=0;o<X.length();o++)X[o]-=48   //字符串转数字
using namespace std;
int o,u,i,n;
struct man{STR x,y,s;}m[1001],w,ans,an;  //x左手,y右手,s是两手乘积
STR divide(STR a,STR b)   //高精除以低精,因为题目说右手最多才10000,所以高/低就行了
{
    STR c;int d=0,k=1,p=0;tonum(a);
    for (o=b.length()-1;o+1;o--)p+=(b[o]-48)*k,k*=10;
    for (o=0;o<a.LEN;o++)
        c.push_back((d*10+a[o])/p+48),d=(d*10+a[o])%p;
    while (c[0]==48)c.erase(c.B,c.B+1);
    return c;
}
STR times(STR a,STR b)   //高精乘
{
    STR c;c.resize(a.LEN+b.LEN,0);
    reverse(a.B,a.E);reverse(b.B,b.E);
    tonum(a);tonum(b);
    for (o=0;o<a.LEN;o++)
        for (u=0;u<b.LEN;u++)
            c[o+u]+=a[o]*b[u],c[o+u+1]+=c[o+u]/10,c[o+u]%=10;
    reverse(c.B,c.E);
    while (!c[0])c.erase(c.B,c.B+1);
    for (o=0;o<c.length();o++)c[o]+=48;
    return c;
}
bool cmp(man a,man b)   //比较函数
{
    if (a.s.LEN<b.s.LEN)return 1;
    if (b.s.LEN<a.s.LEN)return 0;
    return a.s<b.s;
}
int main()
{
    cin>>n;w.s="1";ans.s="0";   //w.s是存前面所有左手的成绩,ans.s就是答案 (最大值)
    for (i=0;i<=n;i++)
        cin>>m[i].x>>m[i].y,m[i].s=times(m[i].x,m[i].y);   //读入+左右相乘
    sort(m+1,m+n+1,cmp);  //将每位大臣的左手右手乘积排序   之后在算答案便是正确答案 证明该题的最底下的题解
    for (i=0;i<=n;i++)   //计算
    {
        an.s=divide(w.s,m[i].y);   //将an.s变成前面所有人左手的乘积除以这个人右手的乘积
        if (!cmp(an,ans))ans.s=an.s;   //比较一下,如果an.s更大的话那么an.s就是目前的最大值 把ans.s变成an.s  到最后的最大值就是ans.s
        w.s=times(w.s,m[i].x);   //更新前面所有人的乘积
    }
    cout<<ans.s;  //华丽di输出
    return 0;  //华丽di结束
}
时间: 2024-09-29 08:06:39

[贪心][高精度][NOIP]国王游戏的相关文章

【贪心+排序】国王游戏

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

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

题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大臣,所获奖赏尽可能的少

洛谷P1080 国王游戏 高精度 贪心 数学推公式

洛谷P1080 国王游戏        数学推公式      高精度    贪心 然而这并不是我打出来的,抄题解... 将左手与右手的乘积从小到大排序,然后计算求最大值即可.(需要高精度) 证明: 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]} 若交换

# 国王游戏(贪心+大数乘除+微扰法证明)

国王游戏(贪心+大数乘除+微扰法证明) 题意:n个大臣和一个国王,左右手都有一个数,排队,国王始终拍在最前面,每个大臣的奖励为这个大臣前面的人的左手上的数之积除以这个大臣右手上的数.构造最优队伍,使得奖励最多的大臣的奖励最少. 证明: 微扰法的使用 我们现在将任意两个人的位置互换,然后考虑他们在交换前和交换后所获得的奖励是多少,其他人的奖励不变: 交换前: 第 \(i\) 个人是 : \(A_0 * A_1*....*A_{i-1}/B_i\) 第 \(i+1\) 个人是 : \(A_0 * A

【NOIP】提高组2012 国王游戏

[算法]贪心+高精度 [题解]学自:http://blog.csdn.net/greatwjj/article/details/12129439 相邻两个人的顺序对前面的人和后面的人的钱都没影响. 令两个人分别为i和i+1,左手数字为a[i],a[i+1],右手数字为b[i],b[i+1],钱为w[i],w[i+1]. 令sum[i]为1...n的左手数字的总乘积. w[i]=sum[i-1]/b[i] w[i+1]=sum[i]/b[i+1] 因为sum[i]=sum[i-1]*a[i] 所以

国王游戏(贪心+大数)

                                                   4824: 国王游戏 时间限制(普通/Java):3000MS/9000MS     内存限制:65536KByte总提交: 2            测试通过:1 描述 恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这n位大臣排成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干

luoguP1080 国王游戏 题解(NOIP2012)(贪心+高精)

luoguP1080 国王游戏 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define il inline #define rg register #define ll long long #define N 10001 #define inf 10000

洛谷P1080 [NOIP2012提高组D1T2]国王游戏 [2017年5月计划 清北学堂51精英班Day1]

P1080 国王游戏 题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每 位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右 手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序, 使得获得奖赏最多的大

noip2012 国王游戏

1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n位大臣排成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手