国王游戏

传送门

又是一道木有看题解就想出来的题

题意:

简而言之
一堆数
求排列
使这些数
经过操作后
最大值最小

解法:

注意:根据题意每个数都有两个数a,b,这里为了方便记作一个数

我们贪心的只考虑第n个数

由于是乘积

所以第n个数确定时

前n-1个数a的乘积就是确定的

所以可以先求出前n个数a的乘积mul

则我们现在需要确定第n个数的值

第n个数的值 即为前n个数a的乘积mul除以第n个数的a,b(都要除)

所以第n个数我们选择a\(\times\)b最大的数

前n-1个数a的乘积就变成mul\(\div\)a

在按照上面方法继续求n-1的数,n-2的数……

求出所有数的值的最大值即为答案


我们不妨证明一下这样做的正确性:

若只有2个大臣

国王、大臣 左、右手分别为\(a_0\ b_0,a_1\ b_1,a_2\ b_2\)

\(a_1\times b_1<a_2\times b_2\)

那么
若把\(a_1,b_1\)放第2个位置 答案即为max(\(\frac{a_0}{b_2},\frac{a_0a_2}{b_1}\))
若把\(a_2,b_2\)放第2个位置 答案即为max(\(\frac{a_0}{b_1},\frac{a_0a_1}{b_2}\))

易得
\(\frac{a_0a_2}{b_1}>\frac{a_0a_1}{b_2},\frac{a_0a_2}{b_1}\ge\frac{a_0}{b_1}\)

所以把max(\(\frac{a_0}{b_2},\frac{a_0a_2}{b_1}\))\(\ge\)max(\(\frac{a_0}{b_1},\frac{a_0a_1}{b_2}\))

所以把\(a_2,b_2\)放第2个位置答案才能最小

虽然只是证了两个数的情况

但是若有更多数a的乘积其实可以看做上述式子\(a_0\)

于是得到结论

\(a_i\times b_i\)的值大的放后 答案才能最小

证毕


代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#define inf 100000000
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
int n;
struct node
{
    int a,b,ab;
}dg[1010];

const int p=1e4;
struct hact
{
    int arr[1000],len;
    hact()
    {
        memset(arr,0,sizeof(arr));
        len=0;
    }
    void print()
    {
        printf("%d",arr[len]);
        dwn(i,len-1,0)
        {
            printf("%04d",arr[i]);
        }
        putchar('\n');
    }
}ans,mul;
hact operator *(hact a,int b)
{
    if(b==0)
    {
        hact c;
        return c;
    }
    hact c;c.len=a.len;ll x=0;
    rep(i,0,c.len)
    {
        c.arr[i]=(1ll*a.arr[i]*b+x)%p;
        x=(1ll*a.arr[i]*b+x)/p;
    }
    while(x>0)
    {
        c.arr[++c.len]=x%p;
        x/=p;
    }
    return c;
}
hact operator /(hact a,int b)
{
    hact c;c.len=a.len;ll x=0;
    dwn(i,c.len,0)
    {
        c.arr[i]=(a.arr[i]+x*p)/b;
        x=(a.arr[i]+x*p)%b;
    }
    dwn(i,c.len,1)
    {
        if(c.arr[i]==0) c.len--;
        else break;
    }
    return c;
}
hact arrmax(hact a,hact b)
{
    if(a.len>b.len)
        return a;
    else if(a.len<b.len)
        return b;
    dwn(i,a.len,0)
    {
        if(a.arr[i]>b.arr[i]) return a;
        else if(a.arr[i]<b.arr[i]) return b;
    }
    return a;
}
bool cmp(node a,node b)
{
    return a.ab<b.ab;
}
int main()
{
    scanf("%d",&n);
    mul.arr[0]=1;
    rep(i,0,n)
    {
        scanf("%d%d",&dg[i].a,&dg[i].b);
        dg[i].ab=dg[i].a*dg[i].b;
        mul=mul*dg[i].a;
    }
    sort(dg+1,dg+n+1,cmp);
    dwn(i,n,1)
    {
        ans=arrmax(ans,mul/dg[i].ab);
        mul=mul/dg[i].a;
    }
    ans.print();
    return 0;
}

posted @ 2019-05-24 09:48  zmy蒟蒻  阅读(265)  评论(0编辑  收藏  举报