[NOIP提高组]2012年 Day1-T2 国王游戏

题目

题目大意

让n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
大臣的位置可以重新排列
求重新排列后的队伍中获奖赏最多的大臣所获得的金币数最小

题目解析

由于相邻的两个大臣交换位置并不影响前面和后面的值
所以这里假设

左手 右手
国王 x0 y0
大臣甲 x1 y1
大臣乙 x2 y2

因为国王位置固定不变,所以

当大臣甲在大臣乙的前面时,k1=max(x0/y1,x0*x1/y2)

当大臣乙在大臣甲的前面时,k2=max(x0/y2,x0*x2/y1)

ans=min(k1,k2)即为所求

n1=x0/y1;n2=x0*x1/y2

n3=x0/y2;n4=x0*x2/y1

不妨设大臣甲在前为最后答案,然后推出关系式.

因为X!=0,所以n4>n1;n2>n3

因为n2

即a0* a1/b2

两边同乘以b1,b2再除以a0,可得

a1* b1

再看到数据规模a,b<=10000,用高精,有点麻烦,不多解释了

代码

#include
#include
#include
#define N 10000
using namespace std;
int n,l,r,t,c,v;
int p[N],ans[N],k[N];
struct A 
{
	int l,r,p;
}a[1005];
bool cmp(A a,A b)
{
	return a.pki)
	 memcpy(ans,k,sizeof(k));
	else if(ansi==ki)
	{
	  for(int i=ansi;ik[i])
	  	 return;
	  	else if(ans[i]=0;i--)
	{
	  p[i]=p[i]*c+t;
	  t=p[i]/10;
	  p[i]%=10;
	}
	return;
}
int main()
{
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++)
	{
	  cin>>a[i].l>>a[i].r;
	  a[i].p=a[i].l*a[i].r;
	}//求每位大臣的左右手乘积 
	sort(a+1,a+1+n,cmp);//排序 
	p[N-1]=l;
	t=0;
	for(int i=N-1;i>=0;i--)
	{
	  p[i]+=t;
	  t=p[i]/10;
	  p[i]%=10;
	}
	for(int i=1;i<=n;i++)
	{
	  c=a[i].l;v=a[i].r;
	  Max();
	  Multiply();
	}
	int t=0;
	while(ans[t]==0&&t

你可能感兴趣的:([NOIP提高组]2012年 Day1-T2 国王游戏)