国王游戏题解

国王游戏

思路:就是按照 a i b i a_ib_i aibi 的大小从小到大排序

证明:我们不妨设两个人分别写了 a 1 , b 1 , a 2 , b 2 a_1,b_1,a_2,b_2 a1,b1,a2,b2 且满足 a 1 b 1 > a 2 b 2 a_1b_1>a_2b_2 a1b1>a2b2 则有 a 2 b 1 = b 2 a 1 \tfrac{a_2}{b_1}=\tfrac{b_2}{a_1} b1a2=a1b2

所以有一下两种情况

  1. 1在2的前面
  2. 1在2的后面

设在设在 1 , 2 1,2 1,2 之前所有人左手乘积为 k k k ,那么对于第一种情况,我们的答案就是

a n s 1 = max ⁡ ( k b 1 , k a 1 b 2 )   = k ⋅ max ⁡ ( 1 b 1 , a 1 b 2 ) \begin{matrix}ans_1&=&\max(\frac{k}{b_1},\frac{ka_1}{b_2})\ &=& k\cdot \max(\frac{1}{b_1},\frac{a_1}{b_2})\end{matrix} ans1=max(b1k,b2ka1) =kmax(b11,b2a1)

∵ a 2 b 1 < a 1 b 2 , a 2 > 1 \because \frac{a_2}{b_1} < \frac{a_1}{b_2},a_2>1 b1a2<b2a1,a2>1
∴ 1 b 1 ≤ a 2 b 1 < a 1 b 2 \therefore \frac{1}{b_1} \leq \frac{a_2}{b_1} < \frac{a_1}{b_2} b11b1a2<b2a1

∴ a n s 1 = k × a 1 b 2 \therefore ans_1=\frac{k \times a_1}{b_2} ans1=b2k×a1

对于第二种,答案就是

a n s 2 = m a x ( k b 2 , k × a 2 b 1 ) ans_2=max(\frac{k}{b_2},\frac{k \times a_2}{b_1}) ans2=max(b2k,b1k×a2)

{ ∵ a 1 > 1 ∴ k × a 1 b 2 ≥ k b 2 ∵ a 2 b 1 < a 1 b 2 ∴ k × a 1 b 2 > k × a 2 b 1 \left\{\begin{matrix} \because a_1>1 \\ \therefore \frac{k \times a_1}{b_2} \ge \frac{k}{b_2}\\ \because \frac{a_2}{b_1}<\frac{a_1}{b_2} \\ \therefore \frac{k \times a_1}{b_2}>\frac{k \times a_2}{b_1}\end{matrix}\right. a1>1b2k×a1b2kb1a2<b2a1b2k×a1>b1k×a2

∴ a n s 1 ≥ a n s 2 \therefore ans_1 \ge ans_2 ans1ans2

所以按照 按照 a i b i a_ib_i aibi 的大小从小到大排序的方法没有问题。

细节:注意高精度

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N;
int a[1005],b[1005],ka,kb;
int ans[20000],t[20000],lena,lent,tt[20000],t2[20000],len;
void _qst_ab(int l,int r)
{
	int i=l,j=r,ma=a[(i+j)>>1],mb=b[(i+j)>>1];
	while(i<=j)
	{
		while(a[i]*b[i]<ma*mb) i++;
		while(a[j]*b[j]>ma*mb) j--;
		if(i<=j)
		{
			swap(a[i],a[j]);
			swap(b[i],b[j]);
			i++;j--;
		}
	}
	if(l<j) _qst_ab(l,j);
	if(i<r) _qst_ab(i,r);
}
void _init()
{
	scanf("%d%d%d",&N,&a[0],&b[0]);
	for(int i=1;i<=N;i++)
	    scanf("%d%d",&a[i],&b[i]);
}
void _get_t(int Left,int Right)
{
	for(int i=1;i<=lent;i++)
	{
		tt[i]+=t[i]*Left;
		tt[i+1]+=tt[i]/10;
		tt[i]%=10;
	}
	lent++;
	while(tt[lent]>=10)
	{
		tt[lent+1]=tt[lent]/10;
		tt[lent]%=10;
		lent++;
	}
	while(lent>1&&tt[lent]==0) lent--;
	len=lent;
	memcpy(t,tt,sizeof(tt));
	memset(tt,0,sizeof(tt));
	for(int i=1,j=len;i<=len;i++,j--)
	    t2[i]=t[j];
	int x=0,y=0;
	for(int i=1;i<=len;i++)
	{
		y=x*10+t2[i];
		tt[i]=y/Right;
		x=y%Right;
	}
	x=1;
	while(x<len&&tt[x]==0) x++;
	memset(t2,0,sizeof(t2));
	for(int i=1,j=x;j<=len;i++,j++)
	    t2[i]=tt[j];
	memcpy(tt,t2,sizeof(t2));
	len=len+1-x;
}
bool _cmp()
{
	if(len>lena) return true;
	if(len<lena) return false;
	for(int i=1;i<=len;i++)
	{
	    if(ans[i]<tt[i]) return true;
	    if(ans[i]>tt[i]) return false;
	}
	return false;
} 
void _solve()
{
	_qst_ab(1,N);
	t[1]=1;lent=1;
	for(int i=1;i<=N;i++)
	{
		memset(tt,0,sizeof(tt));
		len=0;
		_get_t(a[i-1],b[i]);
		if(_cmp())
		{
		    memcpy(ans,tt,sizeof(tt));
		    lena=len;
		}
	}
	for(int i=1;i<=lena;i++)
	    printf("%d",ans[i]);
	printf("\n");
}
int main()
{
	_init();
	_solve();
	return 0;
}

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值