【noip 2012】国王游戏 贪心+高精度

哎,还好今天的高精度没有写挂,但是其实可以只用数组维护的,当年背的一个版,用到现在用习惯了

贪心证明:第i个大臣左右手写的是a,b第j个大臣左右手写的是x,y,i之前的左手分数为q,i->j之间为p那么现在最大分数是max(q/b,q*a*p/y) 化简以后:max(1/b,a*p/y)又因为是向下取整所以1/a==0,1一定小于x*p/y(至于1的情况 自己手写一下发现并不影响)同理交换之后 max(q/y,q*p*x/b)->max(1/y,p*x/b)->p*x/b即是比较min(p*x/b,a*p/y)->min(x/b,a/y)要求x/b<a/y -> x*y<a*b就是冲要条件,好了,剩下的就是高精度了,我直接写了一套版

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define maxn 1010
#define base 10000
using namespace std;
int n;
struct node{
	int a,b;
	LL p;
	bool operator <(const node& b)const{return p<b.p;}
}nod[maxn];
struct Bigint{
	int c[2020],len;
	Bigint(){memset(c,0,sizeof(c));len=1;}
	void Zero(){while(c[len]==0&&len>1)len--;}
	Bigint Write(char* s){
		memset(c,0,sizeof(c));len=1;
		int k=1,ll=strlen(s);
		for(int i=ll-1;i>=0;i--){
			c[len]+=(s[i]-'0')*k;
			k*=10;
			if(k==base){
				k=1,len++;
			}
		}
		Zero();
		return *this;
	}
	void read(){
		char s[10020];
		scanf("%s",s);
		Write(s);
	}
	void Print(){
		Zero();
		printf("%d",c[len]);
		for(int i=len-1;i>=1;i--){
			printf("%04d",c[i]);
		}
	}
	bool operator >(Bigint& b){
		Zero();b.Zero();
		if(len!=b.len)return  len>b.len;
		for(int i=len;i>=1;i--){
			if(c[i]!=b.c[i])return c[i]>b.c[i];
		}
		return false;
	}
	Bigint operator = (const int& b){
		memset(c,0,sizeof(c)),len=1;
		char s[10020];
		sprintf(s,"%d",b);
		Write(s);
		return *this;
	}
	Bigint operator *(const int & b){
		Bigint r;
		r.len=len+4;
		for(int i=1;i<=r.len;i++){
			r.c[i]+=c[i]*b;
		}
		for(int i=1;i<=r.len;i++){
			r.c[i+1]+=r.c[i]/base;
			r.c[i]%=base;
		}
		r.Zero();
		return r;
	}
	Bigint operator / (const int& b){
		Bigint r,k;
		k=*this;
		r.len=len+1;
		for(int i=len;i>=1;i--){
			r.c[i]=k.c[i]/b;
			if(i!=1)k.c[i-1]+=(k.c[i]%b*base);
			k.c[i]/=b;
		}
		r.Zero();
		return  r;
	}
};

void solve(){
	Bigint now;
	Bigint ans;
	Bigint r;
	now=nod[0].a;
	for(int i=1;i<=n;i++){
		r=now/nod[i].b;
		if(r>ans)ans=r;
		now=now*nod[i].a;
	}
	ans.Print();
}

int main(){
	scanf("%d",&n);
	scanf("%d%d",&nod[0].a,&nod[0].b);
	for(int i=1;i<=n;i++)scanf("%d%d",&nod[i].a,&nod[i].b),nod[i].p=(LL)nod[i].a*nod[i].b;
	sort(nod+1,nod+1+n);
	solve();
	return 0;
}/*
3
1 1
2 3
7 4
4 6
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值