【题解】NOIP2012 提高组day1 T2 国王游戏(贪心 高精)


下面给出贪心做法的证明:

    left    right

k     x         y

p1   x1       y1          或                   针对这种情况 我们得到ans1=max(x/y1, x*x1/y2)

p2   x2       y2


    left    right

k     x         y

p2   x2       y2                                针对这种情况 我们得到ans2=max(x/y2, x*x2/y1)

p1   x1       y1


设k1=x/y1, k2=x*x1/y2, k3=x/y2,k4=x*x2/y1

由于x1是整数,我们可以得到k1<k4,k2<k3

若ans1<ans2 我们不难得出k2<k4

展开得到 x1*y1<x2*y2

同理,我们可以以上述不等式为条件,倒着推出ans1<ans2 所以为了让结果更小,我们需要将大臣左右手数字成绩从小到大排序,然后求出其前面所有人左手乘积除以自己右手的最大值。

这道题必须用高精,否则会炸掉。



#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int n;
struct hand
{
	int l;
	int r;
}a[1010];
bool cmp(const hand &a,const hand &b)
{
	return a.l*a.r<b.l*b.r;
}
int ans[40000+10],lans;
int tmp[40000+10],ltmp;
int mmax[40000+10],lmmax;
int ans0[40000+10],lans0;
void f1(int i)  // tmp=ans/a[i].y
{
	memset(tmp,0,sizeof(tmp));
	ltmp=lans;
	lans0=lans;
	int y=a[i].r;
	for(int j=1;j<=lans;j++)
	{
		ans0[j]=ans[j];
	}
	for(int j=lans;j>=1;j--)
	{
		ans0[j-1]+=ans0[j]%y*10;
		tmp[j]=ans0[j]/y;
	}
	while(tmp[ltmp]==0&<mp!=0) ltmp--;
}
void f2()  // max(tmp,mmax)
{
	if(ltmp<lmmax) return;
	if(ltmp==lmmax)
	{
		for(int i=ltmp;i>=1;i--)
		{
			if(tmp[i]<mmax[i]) return ;
			else if(tmp[i]>mmax[i]) break; 
		}
	}
	lmmax=ltmp;
	for(int i=1;i<=ltmp;i++)
		mmax[i]=tmp[i];
}
void f3(int i) // ans*=a[i].l
{
	int y=a[i].l;
	for(int j=1;j<=lans;j++)
		ans[j]*=y;
	for(int j=1;j<=lans;j++)
	{
		ans[j+1]+=ans[j]/10;
		ans[j]%=10;
	}
	while(ans[lans+1]!=0)
	{
		lans++;
		ans[lans+1]=ans[lans]/10;
		ans[lans]%=10;
	}
}
void output()
{
	for(int i=lmmax;i>=1;i--)
	{
		cout<<mmax[i];
	}
	cout<<endl;
}
int main()
{
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);
	scanf("%d",&n);
	n++;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
	}
	sort(a+2,a+n+1,cmp);
	
	while(a[1].l) ans[++lans]=a[1].l%10,a[1].l/=10;
	for(int i=2;i<=n;i++)
	{
		f1(i);
		f3(i);
		f2();
	}
	output();

//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81047479