题目描述:
恰逢 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;
}