您的位置:首页 > 其它

【jzoj3100】【NOIP2012提高组】【国王游戏】【贪心】【高精度】

2016-12-24 19:34 423 查看

题目大意

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

解题思路

写出函数后发现可以写成偏序关系,这样就可以贪心,但是数比较大,需要使用高精度。

code

#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a>b)?b:a)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;

typedef struct{int x,y;}note;
int const oo=2147483647;
int const maxn=3000000,mo=10000;
int n,ans[maxn+10],sum[maxn+10],tmp[maxn+10],anss[10];
struct rec{
int a,b;
friend bool operator<(rec x,rec y){
return x.a*x.b<y.a*y.b;
}
};
rec a[maxn+10];
void mult(int v){
fo(i,1,sum[0])
sum[i]=sum[i]*v;
fo(i,1,sum[0]){
sum[i+1]+=sum[i]/mo;
sum[i]%=mo;
}
for(;sum[sum[0]+1];sum[0]++);
}
void div(int v){
fo(i,0,sum[0])tmp[i]=sum[i];
fd(i,tmp[0],2){
tmp[i-1]+=tmp[i]%v*mo;
tmp[i]/=v;
}
tmp[1]/=v;
fo(i,1,tmp[0]){
tmp[i+1]+=tmp[i]/mo;
tmp[i]%=mo;
}
for(;tmp[0]&&(!tmp[tmp[0]]);tmp[0]--);
}
void maxx(){
if(ans[0]>tmp[0])return;
int flag=0;
if(ans[0]<tmp[0])flag=1;
else{
fd(i,ans[0],1)
if(ans[i]>tmp[i])break;
else if(ans[i]<tmp[i]){flag=1;break;}
}
if(flag)fo(i,0,tmp[0])ans[i]=tmp[i];
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d",&n);
fo(i,0,n)scanf("%d%d",&a[i].a,&a[i].b);
sort(a+1,a+n+1);
//fo(i,0,n)printf("%d%d\n",a[i].a,a[i].b);
sum[0]=sum[1]=1;
mult(a[0].a);
fo(i,1,n){
div(a[i].b);
maxx();
mult(a[i].a);
}
fd(i,ans[0],1){
fo(j,1,4){
anss[j]=ans[i]%10;
ans[i]/=10;
}
anss[0]=4;
if(i==ans[0]){
for(;!anss[anss[0]];anss[0]--);
}
fd(j,anss[0],1)
printf("%d",anss[j]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: