NOIP 2012 国王游戏


solution

  • 实际上还是找一种排序让答案最优

  • 只考虑 a b怎么排,假设前面所有人左手上数的乘积为 P

  • 如果 a 排在 b 前面,那么money[b]=Pleft[a]/right[b]

  • 如果 b 排在 a 前面,那么 money[a]=Pleft[b]/right[a]

  • 假设 a 排在前面更优,那就有money[b]<money[a]

  • Pleft[a]/right[b]<Pleft[b]/right[a]

  • P 约掉,然后把分母乘上去就可以得到left[a]right[a]<left[b]right[b]

  • 所以按照这个排序就可以得到最优解

  • 比较坑的地方是,这个题目需要高精度

  • 建议自己推一下,这种贪心还是比较常见的

code

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 1010

template<typename T>
void input(T &x) {
    x=0; int a=1;
    char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
        if(c=='-') a=-1;
    for(;c>='0'&&c<='9';c=getchar())
        x=x*10+c-'0';
    if(a==-1) x=-x;
    return;
}

struct Minister {

    int l,r,product;

    Minister(int l=0,int r=0,int product=0):
        l(l),r(r),product(product) {}

    bool operator < (const Minister &a)const {
        return product<a.product;
    }

}Game[maxn];

struct Bign {

    static const int BASE=10000;
    static const int MAXN=1010;
    int a[MAXN],len;

    Bign() {
        len=1;
        for(int i=0;i<MAXN;i++)
            a[i]=0;
    }

    Bign(int x) {
        len=0;
        do {
            a[len]=x%BASE;
            x/=BASE;
            len++;
        }while(x!=0);
    }

    Bign(const Bign &GG) {
        *this=GG;
    }

    void Clear() {
        while(a[len-1]==0&&len!=1) len--;
        return;
    }

    Bign operator * (const int &p) const {
        int x=0;
        Bign A=*this;
        for(int i=0;i<len;i++) {
            A.a[i]*=p;
            A.a[i]+=x;
            x=A.a[i]/BASE;
            A.a[i]%=BASE;
        }
        if(x) {
            A.a[len]=x;
            A.len++;
        }
        A.Clear();
        return A;
    }

    Bign operator *= (const int &p) {
        *this=*this*p;
        return *this;
    }

    Bign operator / (const int &p) const {
        Bign ret,A=*this;
        ret.len=len+1;
        for(int i=len-1;i>=0;i--) {
            ret.a[i]=A.a[i]/p;
            if(i!=0) A.a[i-1]+=(A.a[i]%p*BASE);
            A.a[i]/=p;
        }
        ret.Clear();
        return ret;
    }

    Bign operator /= (const int &p) {
        *this=*this/p;
        return *this;
    }

    bool operator < (const Bign &GG) const {
        if(len<GG.len) return true;
        if(len>GG.len) return false;
        for(int i=len-1;i>=0;i--)
            if(a[i]<GG.a[i]) return true;
            else if(a[i]>GG.a[i]) return false;
        return false;
    }

    void Print() {
        Clear();
        printf("%d",a[len-1]);
        for(int i=len-2;i>=0;i--)
            printf("%04d",a[i]);
        printf("\n");
        return;
    }

};

int main() {
    int n;
    input(n);
    for(int i=0;i<=n;i++) {
        int l,r;
        input(l),input(r);
        Game[i]=Minister(l,r,l*r);
    }
    sort(Game+1,Game+n+1);
    Bign now=Game[0].l,Ans;
    for(int i=1;i<=n;i++) {
        Bign GG=now/Game[i].r;
        if(Ans<GG) Ans=GG;
        now*=Game[i].l;
    }
    Ans.Print();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值