[vijos1779][NOIP2012]国王游戏

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

HINT
\(1≤n≤1000,0<a,b<10000\)

Solution
大力推一波证明发现,a在b前优当且仅当\(a_la_r<b_lb_r\).
排个序,后面就是高精度和低精进行运算的事了.(高精/高精更爽不是吗?)

#define N 1005
#define M 40005
struct hand{
	int l,r;
}a[N];
struct number{
	int a[M],n;
	inline void init(){
		n=0;memset(a,0,sizeof(a));
	}
	inline void print(){
		for(int i=n;i;--i)
			printf("%d ",a[i]);
		puts("");
	}
}a1,a2,ans;
int n;
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
bool operator < (hand a,hand b){
	return a.l*a.r<b.l*b.r;
}
bool operator > (number a,number b){
	if(a.n!=b.n) return a.n>b.n;
	for(int i=a.n;i;--i)
		if(a.a[i]!=b.a[i])
			return a.a[i]>b.a[i];
	return false;
}
number operator * (number a,int b){
	number c;c.init();
	c.n=a.n+4;
	for(int i=1;i<=a.n;++i)
		c.a[i]=a.a[i]*b;
	for(int i=1;i<c.n;++i)
		if(c.a[i]>9) c.a[i+1]+=c.a[i]/10,c.a[i]%=10;
	while(c.a[c.n]>9){
		c.a[c.n+1]+=c.a[c.n]/10,c.a[c.n]%=10;++c.n;
	}
	while(c.n>1&&!c.a[c.n]) --c.n;
	return c;
}
number operator / (number a,int b){
	int now=0;number c;c.init();
	for(int i=a.n;i;--i){
		now=(now<<1)+(now<<3)+a.a[i];
		c.a[++c.n]=now/b;now%=b;
	}
	for(int i=(c.n>>1);i;--i) swap(c.a[i],c.a[c.n-i+1]);
	while(c.n>1&&!c.a[c.n]) --c.n;
	return c;
}
inline void Aireen(){
	scanf("%d",&n);
	for(int i=0;i<=n;++i)
		scanf("%d%d",&a[i].l,&a[i].r);
	sort(a+1,a+1+n);
	ans.n=1;
	a1.a[++a1.n]=1;
	a1=a1*a[0].l;
	for(int i=1;i<=n;++i){
		a2=a1/a[i].r;
		a1=a1*a[i].l;
		if(a2>ans) ans=a2;
	}
	for(int i=ans.n;i;--i)
		printf("%d",ans.a[i]);
	printf("\n");
}

2017-10-23 19:06:31

原文地址:https://www.cnblogs.com/AireenYe/p/15602510.html