[NOIP2012提高组]国王旅行

Posted Mrsrz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2012提高组]国王旅行相关的知识,希望对你有一定的参考价值。

题目:洛谷P1080、Vijos P1779。

题目大意:国王和每个大臣左、右手各写了一个数。规定每个大臣得到的金币数为他前面所有人左手的数字的乘积除以他自己右手的数(向下取整),现在国王要改变大臣的排列顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少(国王永远站在最前面)。

解题思路:(贪心)首先,交换相邻两个大臣只会对这两个大臣造成影响,并不会对其他大臣造成影响。

我们考虑大臣i和i+1,设他们左手数字分别为A[i]和A[i+1],右手分别为B[i]和B[i+1],前i-1个大臣和国王左手的数的乘积为S,切A[i]B[i]<=A[i+1]B[i+1]。

原来两个大臣能得到的金币数分别为S/B[i],S*A[i]/B[i+1]。

如果交换,则第一个大臣现在能得到S*A[i+1]/B[i],第二个能得到S/B[i+1]。

由于A[i]B[i]<=A[i+1]B[i+1],所以S*A[i]*B[i]<=S*A[i+1]*B[i+1],所以S*A[i]/B[i+1]<=S*A[i+1]/B[i]。

由此可得大臣以A[i]B[i]从小到大排序,答案越小。

而S*A[i+1]/B[i]>=S/B[i],S*A[i]/B[i+1]>=S/B[i+1],故最大的答案为后面那个大臣的,也保证了答案的正确性。

然后高精度一下就好了。

C++ Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
struct BigInteger {
	static const int BASE=100000000;
	static const int WIDTH=8;
	vector<long long>s;
	BigInteger(long long num=0){*this=num;}
	BigInteger operator = (long long num){
		s.clear();
		do{
			s.push_back(num%BASE);
			num/=BASE;
		} while(num>0);
		return *this;
	}
	BigInteger operator = (const string& str){
		s.clear();
		int x,len=(str.length()-1)/WIDTH+1;
		for(int i=0;i<len;i++){
			int end=str.length()-i*WIDTH;
			int start=max(0,end-WIDTH);
			sscanf(str.substr(start,end-start).c_str(),"%d",&x);
			s.push_back(x);
		}
		return *this;
	}
	BigInteger operator + (const BigInteger& b)const{
		BigInteger c;
		c.s.clear();
		for(int i=0,g=0;;i++){
			if(g==0&&i>=s.size()&&i>=b.s.size())break;
			int x=g;
			if(i<s.size())x+=s[i];
			if(i<b.s.size())x+=b.s[i];
			c.s.push_back(x%BASE);
			g=x/BASE;
		}
		return c;
	}
	bool operator < (const BigInteger& b)const{
		if(s.size()!=b.s.size())return s.size()<b.s.size();
		for(int i=s.size()-1;i>=0;i--)
		if(s[i]!=b.s[i])return s[i]<b.s[i];
		return false;
	}
	bool operator > (const BigInteger& b)const{return b<*this;}
	bool operator <= (const BigInteger& b)const{return !(b<*this);}
	bool operator >= (const BigInteger& b)const{return !(*this<b);}
	bool operator != (const BigInteger& b)const{return b<*this||*this<b;}
	bool operator == (const BigInteger& b)const{return !(b<*this)&&!(*this<b);}
	void cheng(int a){
		vector<long long>c;
		for(int i=0;i<s.size();++i){
			if(c.size()<=i)c.push_back(s[i]*a);else
			c[i]+=s[i]*a;
			if(c[i]/BASE)
			if(c.size()<=i+1)c.push_back(c[i]/BASE);else
			c[i+1]=c[i]/BASE;
			c[i]%=BASE;
		}
		s=c;
	}
	void chu(int a){
		vector<long long>c(s);
		if(s.back()/a)c[s.size()-1]=s.back()/a,s[s.size()-1]%=a;else
		c.pop_back();
		for(int i=s.size()-2;i>=0;--i){
			long long num=s[i+1]*BASE+s[i];
			c[i]=num/a;
			num%=a;
			s[i]=num;
		}
		s=c;
	}
};
ostream& operator << (ostream &out,const BigInteger& x){
	out<<x.s.back();
	for(int i=x.s.size()-2;i>=0;i--){
		char buf[20];
		sprintf(buf,"%08d",x.s[i]);
		for(int j=0;j<strlen(buf);j++)out<<buf[j];
	}
	return out;
}
istream& operator >> (istream &in,BigInteger& x){
	string s;
	if(!(in>>s))return in;
	x=s;
	return in;
}
struct DC{
	int a,b;
	bool operator < (const DC&rhs)const{return a*b<rhs.a*rhs.b;}
}p[1005];
int n;
BigInteger sum,Div,ans;
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=0;i<=n;++i)cin>>p[i].a>>p[i].b;
	sort(p+1,p+n+1);
	sum=ans=p[0].a;
	for(int i=1;i<=n;++i){
		Div=sum;
		Div.chu(p[i].b);
		if(ans<Div)ans=Div;
		sum.cheng(p[i].a);
	}
	cout<<ans<<endl;
	return 0;
}

 

以上是关于[NOIP2012提高组]国王旅行的主要内容,如果未能解决你的问题,请参考以下文章

国王游戏 2012年NOIP全国联赛提高组(贪心+高精)

NOIP 2012 提高组 DAY1 T2 国王游戏

NOIP2012提高组国王游戏 贪心 + 高精度

NOIP2012提高组开车旅行

NOIP2012提高组开车旅行 倍增

[NOIP2012] 提高组 洛谷P1081 开车旅行