『NOIP 2012』国王游戏 (贪心 + 高精度)

国王游戏

题目描述

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

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



解题思路

非常巧妙的一道贪心题,思维能力太差的蒟蒻我还是得看题解 [害怕.jpg]

我们首先要发现一个非常玄学牛逼的一个贪心原则:左右手乘积小的人要放在前面 

我们一步步证明这个定理抄袭大佬的证明

假设我们现在有3个人,站成这样的队列:

1.

-----------队首------------

\(A\) \(B\)

\(a_0\) \(b_0\)

\(a_1\) \(b_1\)

-----------队尾------------

\(a\)代表左手,\(b\)代表右手,\(AB\)表示国王。

此时的\(ans1=max(\frac A {b_0} , \frac {A \times a_0}{b_1})\)

带换一下\(ans1=max(k_1,k_2)\)

2.

-----------队首------------

\(A\) \(B\)

\(a_1\) \(b_1\)

\(a_0\) \(b_0\)

-----------队尾------------

此时的\(ans2=max(\frac A {b_1} , \frac {A \times a_1}{b_0})\)

带换一下\(ans2=max(k_3,k_4)\)

显然,我们发现\(k_1< k_4\),\(k_2 > k_3\)

我们直接钦定第一种方案是更优的。

那么就会有\(ans1<ans2\),也就是\(k_4>k_2\)

代成原来的值就是$ \frac {{A} \times a_1}{b_0} > \frac {A \times a_0}{b_1}$

\(\frac{a_1}{b_0}>\frac{a_0}{b_1}\)

再次化简就可以得到\(a_1 \times b_1 > a_0 \times a_1\)

这样就可以看出来了,我们应该把\(a_i \times b_i\)小得人放在前边。



代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=1050;
const int wei=1e8;
struct nod{
    ll a,b,c;
};
int n;
ll A,B,cnt=0;
nod p[maxn];
ll mu[maxn],dd[maxn],tmp[maxn],ans[maxn],len,len_ans=0;
inline void read(register ll &x){
    x=0; register char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
}
inline bool cmp(nod x,nod y){
    return x.c<y.c;
}
inline void mul(ll x){
    for(register int i=1;i<=cnt;i++)mu[i]*=x;
    for(register int i=1;i<cnt;i++)
        mu[i+1]+=mu[i]/wei,mu[i]%=wei;
    while(mu[cnt]>=wei){
        mu[cnt+1]+=mu[cnt]/wei,mu[cnt]%=wei,cnt++;
    }
}
inline void div(ll x){
    len=0;
    memcpy(tmp,mu,sizeof(tmp));
    for(register int i=cnt;i>=1;i--){
        dd[i]=tmp[i]/x;
        if(dd[i]&&!len)len=i;
        tmp[i-1]+=(tmp[i]%x)*wei;
    }
}
inline void print(){
    printf("%lld",ans[len_ans]);
    for(register int i=len_ans-1;i>=1;i--){
        ll tmp=ans[i],cheng=1,j=1;
        for(;j<=8;j++){
            if(!(tmp/cheng))break;
            cheng*=10;
        }
        for(;j<=8;j++)putchar('0');
        if(ans[i])printf("%lld",ans[i]);
    }
}
inline void comp(){
    if(len<len_ans)return;
    if(len>len_ans)memcpy(ans,dd,sizeof(ans)),len_ans=len;
    else {
        for(register int i=len;i>=1;i--){
            if(dd[i]>ans[i]){
                memcpy(ans,dd,sizeof(ans));
                return ;
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    read(A),read(B);
    for(register int i=1;i<=n;i++){
        read(p[i].a),read(p[i].b);
        p[i].c=p[i].a*p[i].b;
    }
    sort(p+1,p+n+1,cmp);
    while(A)mu[++cnt]=A%wei,A/=wei;
    for(register int i=1;i<=n;i++)
        div(p[i].b),comp(),mul(p[i].a);
    print();
}

猜你喜欢

转载自www.cnblogs.com/Fang-Hao/p/9688099.html