哎,还好今天的高精度没有写挂,但是其实可以只用数组维护的,当年背的一个版,用到现在用习惯了
贪心证明:第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
*/