• P1080国王游戏


    传送

    最大值最小什么的一看就是二分了qwq

    然鹅并不知道怎么检查,所以我们换个思路

    我们要求出最小的最大值,这肯定和大臣的排列有关,会不会有什么规律?

    先看看只有两个大臣的情况

    排列:1 2,ans1=max{a0/b1,a0a1/b2}

    排列:2 1,ans2=max{a0/b2,a0a2/b1}

    显然a0/b1<a0a2/b1,a0/b2<a0a1/b2,所以最大值取决于a0a1/b2和a0a2/b1

    为了让最大值最小,当ans1>ans2的时候,我们就会调换1,2的顺序

    所以就是a0a1/b2>a0a2/b1,也就是a1b1>a2b2的时候就会调换。

    综上可得按照a*b从小到大排序

    其实这个题的难点不在排序思路,在于高精。

    a,b<10000,n<1000,最坏情况ans=100001000,爽

    建议结合代码食用

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll read()
    {
        char ch=getchar();
        ll x=0;bool f=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<3)+(x<<1)+(ch^48);
            ch=getchar();
        }
        return f?-x:x;
    }
    struct rr
    {
        ll a,b;
    }ren[1009];
    ll n,aa,bb,sa[7009],now[7009],ma[7009],lenm=1,lens=1,lenn=1;//sa记录大臣们左手上的数的乘积,now记录当前大臣的金币,ma记录最大值
    bool cmp(rr t,rr w)
    {
        return t.a*t.b<w.a*w.b;
    }
    //以下是高精
    void cheng(ll k)//高精乘
    {
        sa[1]*=k;
        for(int i=2;i<=lens;i++)
        {
            sa[i]=sa[i-1]/10+sa[i]*k;
            sa[i-1]%=10;
        }
        while(sa[lens]>=10)
        {
            lens++;
            sa[lens]=sa[lens-1]/10;
            sa[lens-1]%=10;
        }
    }
    void chu(ll k)
    {
        int j=0,x=0;
        memset(now,0,sizeof(now));
        for(int i=lens;i>=1;i--)
        {
            j++;
            x=x*10+sa[i];
            now[j]=x/k;
            x=x-now[j]*k;
        }
        for(int i=1;i<=j/2;i++)//由于高精除单精是从第一位表示高位,所以要把now反过来,注意是i<=j/2,不是i<=j
          {
              int tmp=now[i];
              now[i]=now[j-i+1];
              now[j-i+1]=tmp;
          }
        while(now[j]==0&&j>1)
          j--;
        lenn=j;   
    }
    void max_()//进行比较
    {
        if(lenn>lenm)
        {
            for(int i=lenn;i>=1;i--)
             ma[i]=now[i];
             lenm=lenn;//别漏了
            return ; 
        }
        if(lenn<lenm) return ;
        for(int i=lenn;i>=1;i--)
        {
            if(now[i]<ma[i])
             break;
            if(now[i]>ma[i])//找到第一位比ma对应位小的
            {
                for(int j=i;j>=1;j--)
                {
                    ma[j]=now[j];
                }
                return ;
            } 
        }
        return ;
    }
    int main()
    {
        sa[1]=1;
        n=read();ren[0].a=read();ren[0].b=read();
        for(int i=1;i<=n;i++)
         ren[i].a=read(),ren[i].b=read();
        sort(ren+1,ren+1+n,cmp);    
        for(int i=1;i<=n;i++) 
        {   
           cheng(ren[i-1].a);
            chu(ren[i].b);
            max_();  
        }
        for(int i=lenm;i>=1;i--)
          printf("%lld",ma[i]);
    }
  • 相关阅读:
    mongodb安装与启动
    js数组操作
    js字符串操作
    js原型对象和原型链
    Js 原型对象与原型链
    zepto
    闭包的理解
    JSON与XML的区别比较
    ajax 异步请求四个步骤
    angularJS之项目知识
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/11180375.html
Copyright © 2020-2023  润新知