国王游戏

恰逢 H H国国庆,国王邀请 nn 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 nn 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输入输出格式
输入格式:
第一行包含一个整数 nn,表示大臣的人数。

第二行包含两个整数 aa和 bb,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来 n n行,每行包含两个整数 aa 和 bb,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式:
一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

输入输出样例
输入样例#1: 复制
3
1 1
2 3
7 4
4 6
输出样例#1: 复制
2
说明
【输入输出样例说明】

按 11、22、33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按 11、33、22 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按 22、11、33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按 22、33、1 1这样排列队伍,获得奖赏最多的大臣所获得金币数为 99;

按 33、11、2 2这样排列队伍,获得奖赏最多的大臣所获得金币数为 22;

按 33、22、11 这样排列队伍,获得奖赏最多的大臣所获得金币数为 99。

因此,奖赏最多的大臣最少获得 2 2个金币,答案输出 22。

【数据范围】

对于 20%的数据,有 1≤ n≤ 10,0 < a,b < 81≤n≤10,0<a,b<8;

对于 40%的数据,有 1≤ n≤20,0 < a,b < 81≤n≤20,0<a,b<8;

对于 60%的数据,有 1≤ n≤1001≤n≤100;

对于 60%的数据,保证答案不超过 10^910
9

对于 100%的数据,有 1 ≤ n ≤1,000,0 < a,b < 100001≤n≤1,000,0<a,b<10000。

NOIP 2012 提高组 第一天 第二题
分析:最简单的方法是用全排列来做,很显然n的阶乘会超时,理解一下题意,10000的规模令我想到贪心,刚开始想到按照右手的数贪,很显然不对例如:1 10 1000 5(不算国王) 求得ans=100正确来说ans为0;根据推导V[i]=a[i-1]~a[I-n]/b[i] 所以金币的获得与两个因素有关。
正确的贪心方法是按照左右手乘积贪。在加上一个高精度,完美AC(高精度的处理有点麻烦,注意字符串比较大小是逐字节比较)

  #include <bits/stdc++.h>
 using namespace std;
 long long n,g,fw,lo;
 string ans;
 const int bi=4000;
 int t[4001],tt[4001];
 struct A
 {
 	int a,b,c;
 }a[1001];
 bool cmp (A a,A b)
 {
 	return a.c<b.c;
 } 
 void gj(int s)
 {
 	int c=0;
 	for (int i=bi;i>=1;i--)
 	{
 		t[i]*=s;
 		t[i]+=c;
 		c=t[i]/10;
 		t[i]%=10;
 	//	tt[bi+1-i]=t[i];
	 }
	 int j=0;
	 while (t[j]==0) j++;
	 for (int i=j;i<=bi;i++)
	   tt[i-j+1]=t[i];
	 lo=bi-j+1;
	 return;
	 
 }
 string gj2(int s)
 {
 	bool p=0;
 	string anss="";
 	int i=1,c=0;
 	for ( i=1;i<=lo;i++)
 	{
 		tt[i]+=(c*10);
 		c=tt[i]%s;
 		if (tt[i]>s)  
		 	p=1;
		tt[i]/=s;
     }
     p=0;
	 for (int j=1;j<=lo;j++)
	 {
	 	if (tt[j]>0)
	 	{
	 		anss+=tt[j]+'0';
	 		p=1;
		 }
		else if (p==1)
		anss+='0';
	 }
//	 cout<<anss<<endl;
	 return anss;
 }
 int main()
 {
 	
 	cin>>n;
 	long long q;
 	cin>>g>>fw;
 	a[0].a=g;
 	for (int i=1;i<=n;i++)
 	{
 		cin>>a[i].a>>a[i].b;
 		a[i].c=a[i].a*a[i].b;
	 }
 	sort (a+1,a+n+1,cmp);
	 t[bi]=1;	
 	for (int i=1;i<=n;i++)
 	{
	 	gj(a[i-1].a);
		//string anst;	 	
 		//anst=gj2(a[i].b);
 		//if (anst.size()=gj)
 		string bj=gj2(a[i].b);
 		if (bj.size()>ans.size()) ans=bj;
		if (bj.size()==ans.size())
		{
			for (int i=0;i<ans.size();i++)
			{
				if (bj[i]>ans[i]) 
				{
					ans=bj;
					break;
				}
				if (bj[i]<ans[i]) break;
			}
		 } 
	 }
//	int qq=ans.size()-1;
//	while (ans[qq]=='0') qq--;
 //   for (int i=0;i<=qq;i++)
      cout<<ans;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值