NOIP提高组2012 国王游戏

39 篇文章 0 订阅
32 篇文章 0 订阅

题目描述:

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输入输出格式
输入格式:

第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手
和右手上的整数。

输出格式:

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

题目思路:高精度+贪心:

#include<iostream>
#include<cstdio>
#include<algorithm> 
#include<cstring>
using namespace std;
struct node{
    int a,b,m;
}x[100000];
int a[100000],b[100000],d[100000],max1[100000],l,maxl=0,ansr=0,ansl=0,r;
char s[100000];
int cmp(node a,node b){
    if (a.m==b.m) return a.b<b.b;
    return a.m < b.m;
}
void lily(int a[],int x){//高精乘
    int i;
    memset(d,0,sizeof(d));
    for(i=1;i<=l;i++)d[i]=a[i]*x;
    for(i=1;i<=l;i++){
        if(d[i]/10){
             d[i+1]+=d[i]/10;
             d[i]%=10;
         }         
    }
    while(d[l+1])l++;
    while(d[l]/10){
        d[l+1]+=d[l]/10;
        d[l]%=10;
        l++;
    }
    for(i=1;i<=l;i++)a[i]=d[i];
}
void lily2(int a[],int x){//高精除
    memset(d,0,sizeof(d));
    int m=0;
    for(int i=1;i<=l;i++){
         d[i]=(a[i]+m*10)/x;
         m=(a[i]+m*10)%x;

    } 
    int c=0;
    for(int i=1;i<=l;i++){//判断
        if(d[i]){
            c=1;
            break;
        }
    }
    if(c==1){
        int i;
        for(i=1;d[i]==0;i++);
            r=i;
        for(i=i;i<=l;i++){
            if(d[i]>max1[i]&&l-r+1==maxl || l-r+1>maxl){
                for(int j=r;j<=l;j++)max1[j]=d[j];
                maxl=l-r+1;
                break;
            }
            if(maxl>l-r+1 || d[i]<max1[i])break;
        }
    }
}
int main(void){
    int i,j=0,k,n;
    scanf("%d",&n);
    for(i=0;i<=n;i++){
        scanf("%d%d",&x[i].a,&x[i].b);
        x[i].m=x[i].a*x[i].b;
    }
    sort(x+1,x+n+1,cmp);//贪心按双手乘积排列
    while(x[0].a){
        s[j]=x[0].a%10+48;
        x[0].a/=10;
        j++;
    }
    l=strlen(s);
    for(i=1;i<=l;i++) a[i]=s[i-1]-48;//高精
    for(i=1;i<=l;i++) b[i]=s[l-i]-48;
    for(i=1;i<=n;i++){
        lily2(b,x[i].b);
        lily(a,x[i].a);
        for(j=1;j<=l;j++){
            b[j]=a[l-j+1];
        }
    }
    for(i=r;i<=maxl+r-1;i++)printf("%d",max1[i]);//输出
    return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值