NOIP2012day1 国王游戏(贪心)

题意

https://www.luogu.org/problemnew/show/P1080

思路

按冒泡排序的原则,先分析两两是否交换的情况:
假设大臣 1 1 和大臣 2,前面的大臣左手边数的成绩为常数 c c
1 排在前面时,最大值是 max{cb1,ca1b2} max { c b 1 , c a 1 b 2 }
2 2 排在前面时,最大值是 max{cb2,ca2b1}
假设 1 1 在前面更优,就是 max{cb1,ca1b2}<max{cb2,ca2b1}.
提出 c c ,即为 max{1b1,a1b2}<max{1b2,a2b1}.
1b1a2b1,1b2a1b2 1 b 1 ≤ a 2 b 1 , 1 b 2 ≤ a 1 b 2
所以原式又化简成 a1b2<a2b1 a 1 b 2 < a 2 b 1
交叉一下就是 a1b1<a2b2 a 1 b 1 < a 2 b 2
这个时候贪心决策就比较明显了,直接按 a,b a , b 的乘积排序即可,范围比较大,需要压 4 4 <script type="math/tex" id="MathJax-Element-1850">4</script> 位高精。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(register int i=(x);i<=(y);++i)
#define DOR(i,x,y) for(register int i=(x);i>=(y);--i)
#define N 1003
typedef long long LL;
using namespace std;
int n;
struct node{int a,b;}s[N];
bool cmp(node x,node y){return x.a*x.b<y.a*y.b;}

struct BigInt
{
    int num[2003],n;
    void clr(){memset(num,0,sizeof(num));n=0;}
    void operator =(int x)
    {
        clr();
        do
        {
            num[n++]=x%10000;
            x/=10000;
        }while(x);
    }
    BigInt operator /(const int &x)const
    {
        BigInt res;
        res=(*this);
        DOR(i,n-1,1)
        {
            res.num[i-1]+=(res.num[i]%x)*10000;
            res.num[i]/=x;
        }
        res.num[0]/=x;
        while(n>1&&res.num[res.n-1]==0)res.n--;
        return res;
    }
    bool operator <(const BigInt &_)const
    {
        if(n!=_.n)return n<_.n;
        DOR(i,n-1,0)if(num[i]!=_.num[i])return num[i]<_.num[i];
        return false;
    }
    void operator *=(const int &x)
    {
        FOR(i,0,n-1)num[i]*=x;
        FOR(i,0,n-1)
        {
            num[i+1]+=(num[i]/10000);
            num[i]%=10000;
            if(num[n])n++;
        }
    }
    void Print()
    {
        printf("%d",num[n-1]);
        DOR(i,n-2,0)printf("%04d",num[i]);
    }
};
void chk_max(BigInt &x,BigInt y){if(x<y)x=y;}

int main()
{
    scanf("%d",&n);
    FOR(i,0,n)scanf("%d%d",&s[i].a,&s[i].b);
    sort(s+1,s+1+n,cmp);
    BigInt sum,ans;
    sum=s[0].a,ans=0;
    FOR(i,1,n)
    {
        chk_max(ans,sum/s[i].b);
        sum*=s[i].a;
    }
    ans.Print();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值