NOIP2012国王游戏

主要考察:贪心

思路

对于第i个大臣和第j个大臣:

如果第 i个大臣放第 j个大臣前面对答案的贡献小些,那么第 i个大臣就放第 j个大臣前面 ​​​​​​​

所以就是使 a\left [ i \right ].x/a\left [ j \right ].y<a\left [ j \right ].x/a\left [ i \right ].j

所以就是a\left [ i \right ].x*a\left [ i \right ].y<a\left [ j \right ].x*a\left [ j \right ].y

然后高精度部分压位,这样快得多,20ms,

乘法部分相当于高精度乘低精度

除法部分相当于高精度除低精度

AC代码
#include<bits/stdc++.h>
using namespace std;
int read()
{
    char s;
    int k=0,base=1;
    while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9'));
    if(s==EOF)exit(0);
    if(s=='-')base=-1,s=getchar();
    while(s>='0'&&s<='9')
    {
        k=k*10+(s-'0');
        s=getchar();
    }
    return k*base;
}
void write(int x)
{
    if(x<0)
    {
        putchar('-');
        write(-x);
    }
    else
    {
        if(x/10)write(x/10);
        putchar(x%10+'0');
    }
}
int n,A,B;
struct node
{
    int x,y;
} a[1010];
bool cmp(node aa,node bb)
{
    if (aa.x*aa.y==bb.x*bb.y) return aa.y<bb.y;
    return (aa.x*aa.y)<(bb.x*bb.y);
}
int sum[1010];
int ans[1010],ls;
int p[1010],lp;
int m;//sum长度
int P;
bool Max()//比大小,ans>p: true
{
    int i=1;
    while (p[i]==0&&i<=lp) i++;//去掉前面的0
    int j=1;
    while (ans[j]==0&&j<=ls) j++;
    if (lp-i+1>ls-j+1) return false;//p的位数>ans的位数
    if (lp-i+1<ls-j+1) return true;
    while (i<=lp&&j<=ls)//一位一位的比较
    {
        if (p[i]<ans[j]) return true;
        if (p[i]>ans[j]) return false;
        i++;
        j++;
    }
    return false;
}
void cheng(int d)
{
    for (int i=1;i<=m;i++)
        sum[i]*=a[d].x;//高精度乘法
    for (int i=1;i<=m;i++)//进位
    {
        sum[i+1]+=sum[i]/10000;
        sum[i]%=10000;
    }
    if (sum[m+1]!=0) m++;
}
void div(int d)
{
    memset(ans,0,sizeof(ans));
    ls=1;
    while (m>0&&sum[m]==0) m--;//去掉前导0
    P=0;
    int flag=0;
    for (int i=m;i>=1;i--)//高精度除法(模拟竖式)
    {
        P=P*10000+sum[i];
        ans[++ls]=P/a[d].y;
        if (ans[ls]==0&&!flag) ls--; else flag=1;
        P%=a[d].y;
    }
}
int main()
{
    n=read();
    A=read();
    B=read();
    for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
    sort(a+1,a+n+1,cmp);
    m=1;
    sum[1]=A;
    for (int i=1;i<=n;i++)
    {
        div(i);
        if (Max())
        {
            lp=ls;
            memcpy(p,ans,sizeof(ans));
        }
        cheng(i);
    }
    int i=0;
    while (i<=lp&&p[i]==0) i++;
    printf("%d",p[i]);i++;
    for (;i<=lp;i++)//输出
    {
        if (0<=p[i]&&p[i]<=9) printf("000%d",p[i]);else
        if (10<=p[i]&&p[i]<=99) printf("00%d",p[i]);else
        if (100<=p[i]&&p[i]<=999) printf("0%d",p[i]);else
        printf("%d",p[i]);
    }
    return 0;
}
  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值