码迷,mamicode.com
首页 > 其他好文 > 详细

[NOIP2012提高组]国王旅行

时间:2017-09-18 22:27:20      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:题目   syn   ati   c++   with   main   取整   ase   cstring   

题目:洛谷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提高组]国王旅行

标签:题目   syn   ati   c++   with   main   取整   ase   cstring   

原文地址:http://www.cnblogs.com/Mrsrz/p/7545044.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!