其他分享
首页 > 其他分享> > $Luogu P1080$ 国王游戏

$Luogu P1080$ 国王游戏

作者:互联网

链接

背景

NOIP2012 Day1 T2

题意

给定国王和 \(n\) 个大臣左右手上的数 \(a\) 和 \(b\) 。每个大臣 \(i\) 获得金币为 \(国王左手金币数 \times \frac{\prod_{j=1}^{i-1} a[j]}{b[i]}\) ,请设计一个排队顺序使得到金币数最多的大臣获得的金币数最小,注意国王只能在队首。

解法

咕咕咕

\(trick\)

以排序为贪心策略的题目大概率是用微扰法(邻项交换法)证明的。最终结果的序列一定不能通过交换使得答案变大。

细节

1.每个大臣进队时,乘入结果的是上一个大臣左手上的数,除以的是自己手上的数。

2.此题只有 \(60\%\) 的数据答案在 \(10^9\) 以内,其余的均要使用高精度解决。高精度模板

代码

\(View\) \(Code\)

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int ret=0,f=1;
    char ch=getchar();
    while(ch>'9'||ch<'0')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ret=(ret<<1)+(ret<<3)+ch-'0';
        ch=getchar();
    }
    return ret*f;
}
int n,lens=1,lenm=1,lena=1,sum[10005]={0,1},maxn[10005]={0,1},ans[10005];
struct node
{
    int a;
    int b;
}s[1005];
inline bool cmp(node x,node y)
{
    return x.a*x.b<y.a*y.b;
}
inline void mul(int x)
{
    int tmp=0;
    for(register int i=1;i<=lens;i++)
        sum[i]*=x;
    for(register int i=1;i<=lens;i++)
    {
        tmp+=sum[i];
        sum[i]=tmp%10;
        tmp/=10;
    }
    while(tmp)
    {
        lens++;
        sum[lens]=tmp%10;
        tmp/=10;
    }
}
inline void div(int x)
{
    memset(ans,0,sizeof(ans));
    lena=lens;
    int tmp=0;
    for(register int i=lena;i;i--)
    {
        tmp*=10;
        tmp+=sum[i];
        if(tmp>=x)
        {
            ans[i]=tmp/x;
            tmp%=x;
        }
    }
    while(ans[lena]==0)
    {
        if(lena==1)
            break;
        lena--;
    }
}
inline void cmp1()
{
    if(lena>lenm)
    {
        for(register int i=1;i<=lena;i++)
            maxn[i]=ans[i];
        lenm=lena;
    }
    else if(lenm==lena)
    {
        for(register int i=lena;i;i--)
        {
            if(maxn[i]<ans[i])
            {
                for(register int j=1;j<=lena;j++)
                    maxn[j]=ans[j];
                lenm=lena;
                break;
            }
        }
    }
}
inline void write()
{
    for(register int i=lenm;i;i--)
        printf("%d",maxn[i]);
}
int main()
{
    n=read();
    s[0].a=read();
    s[0].b=read();
    for(register int i=1;i<=n;i++)
    {
        s[i].a=read();
        s[i].b=read();
    }
    sort(s+1,s+n+1,cmp);
    for(register int i=1;i<=n;i++)
    {
        mul(s[i-1].a);
        div(s[i].b);
        cmp1();
    }
    write();
    return 0;
}

标签:lena,ch,游戏,int,Luogu,金币,大臣,P1080,国王
来源: https://www.cnblogs.com/Peter0701/p/11237138.html