jzoj(高中)3100. 【NOIP2012提高组】国王游戏

题目链接

题解:将Ai*Bi得出Ci,然后把Ci从小到大排一遍(A和B数组一起跟着C数组动),得出最佳队列,接着枚举每个大臣的金币数即可(要用高精度乘低精度和高精度除低精度)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
long long int n,a[1001],b[1001],c[1001],maxn[5001],an[5001],nm,na,v[5001],nv;
void px(long long int l,long long int r)
{
    long long int x=l,y=r,mid=c[(l+r)/2];
    while(x<=y)
    {
        while(c[x]<mid)x++;
        while(c[y]>mid)y--;
        if(x<=y)
        {
            long long int t=a[x];
            a[x]=a[y];
            a[y]=t;
            t=b[x];
            b[x]=b[y];
            b[y]=t;
            t=c[x];
            c[x]=c[y];
            c[y]=t;
            x++;y--;
        }
    }
    if(x<r)px(x,r);
    if(l<y)px(l,y);
}
void cheng(long long int x)
{
    for(int i=1;i<=na;i++)
    {
        an[i]*=a[x];
    }
    for(int i=1;i<=na;i++)
    {
        if(an[i]>9)
        {
            an[i+1]+=an[i]/10;
            an[i]%=10;
            if(i+1>na)
            {
                na++;
            }
        }
    }
    while(an[na]==0&&na>1)na--;
}
void pd()
{
    if(nm>nv)
    {
        return ;
    }
    if(nm==nv)
    {
        for(long long int i=nv;i>=1;i--)
        {
            if(maxn[i]>v[i])
            {
                return ;
            }
            else if(v[i]>maxn[i])
            {
                break;
            }
        }
    }
    memset(maxn,0,sizeof(maxn));
    for(long long int i=1;i<=nv;i++)
    {
        maxn[i]=v[i];
    }
    nm=nv;
}
void chu(long long int x)
{
    memset(v,0,sizeof(v));nv=0;
    long long int sd=0;
    for(long long int i=na;i>=1;i--)
    {
        sd=sd*10+an[i];
        if(sd>=b[x])
        {
            nv=max(nv,i);
            v[i]=sd/b[x];
            sd-=b[x]*v[i];
        }
    }
    pd();
}
int main()
{
//  freopen("game.in","r",stdin);
//  freopen("game.out","w",stdout);
    scanf("%lld",&n);
    for(int i=0;i<=n;i++)
    {
        scanf("%lld %lld",&a[i],&b[i]);c[i]=a[i]*b[i];
    }
    px(1,n);
    an[1]=1;na=1;cheng(0);
    for(int i=1;i<=n;i++)
    {
        chu(i);
        cheng(i);
    }
    for(long long int i=nm;i>=1;i--)
    {
        printf("%lld",maxn[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值