NOIP2012【国王游戏】

NOIP2012【国王游戏】_第1张图片NOIP2012【国王游戏】_第2张图片

【题解】

  一开始看着题觉得是二分答案(最大值的最小值),后来发现不满足单调性

  再后来发现可以用贪心做:只需把大臣按照左手*右手升序排序即可

  证明:

   很显然前面的大臣位置随便调换对后面的大臣并没有影响

  那么假设现在已经排了i-1个大臣,p=a[1]*a[2]*a[3]*……*a[i-1];

  第i个大臣的钱w[i]=p/b[i],第i+1个大臣的钱w[i+1]=p*a[i]/b[i+1]

  若i+1大臣在i大臣前面

  第i个大臣的钱w[i]=p*a[i+1]/b[i],第i+1个大臣的钱w[i+1]=p/b[i+1]

  显然p*a[i+1]/b[i]>p/b[i]  &&  p*a[i]/b[i+1]>p/b[i+1]

  所以两个里面的最大值在p*a[i+1]/b[i] 和 p*a[i]/b[i+1] 之间  

  若p*a[i+1]/b[i] > p*a[i]/b[i+1](这样就是i+1大臣排在i后面最大值会更小) 则 a[i+1]*b[i+1]>a[i]*b[i]

  所以如果要让大臣得到的钱的最大值最小就要保证两个相邻的大臣,前面的左手*右手<后面的左手*右手

  (一年前打的题目,现在写题解还要写好久,果然我还是太菜了)

   详见代码(记得打高精度,还有interesting的高精除法噢233)

   

#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

struct info
  {
    int l,r,k;
  }num[1001];
  
inline bool cmp(const info &a,const info &b)
  {
	return a.k0) f[++f[0]]=t; 
      }
    t=0;
    for (int i=f[0];i>=1;i--)
	  {
    	t+=f[i];f[i]=t/num[n].r;
    	t%=num[n].r;
    	t*=10000;
      }  
    for (;f[f[0]]==0 && f[0]>0;f[0]--);
    if (f[f[0]]==0) printf("1");else printf("%d",f[f[0]]);
    for (int i=f[0]-1;i>=1;i--)
	  {
    	if (f[i]<10) printf("000");
    	if (f[i]<100 && f[i]>=10) printf("00");
    	if (f[i]<1000 && f[i]>=100) printf("0");
		printf("%d",f[i]);
      }
}

你可能感兴趣的:(历届NOIP,高精度,贪心)