题意
https://www.luogu.org/problemnew/show/P1080
思路
按冒泡排序的原则,先分析两两是否交换的情况:
假设大臣
1
1
和大臣 ,前面的大臣左手边数的成绩为常数
c
c
:
当 排在前面时,最大值是
max{cb1,ca1b2}
max
{
c
b
1
,
c
a
1
b
2
}
;
当
2
2
排在前面时,最大值是 ;
假设
1
1
在前面更优,就是 .
提出
c
c
,即为 .
又
1b1≤a2b1,1b2≤a1b2
1
b
1
≤
a
2
b
1
,
1
b
2
≤
a
1
b
2
所以原式又化简成
a1b2<a2b1
a
1
b
2
<
a
2
b
1
交叉一下就是
a1b1<a2b2
a
1
b
1
<
a
2
b
2
这个时候贪心决策就比较明显了,直接按
a,b
a
,
b
的乘积排序即可,范围比较大,需要压
4
4
<script type="math/tex" id="MathJax-Element-1850">4</script> 位高精。
代码
#include<bits/stdc++.h>
#define FOR(i,x,y) for(register int i=(x);i<=(y);++i)
#define DOR(i,x,y) for(register int i=(x);i>=(y);--i)
#define N 1003
typedef long long LL;
using namespace std;
int n;
struct node{int a,b;}s[N];
bool cmp(node x,node y){return x.a*x.b<y.a*y.b;}
struct BigInt
{
int num[2003],n;
void clr(){memset(num,0,sizeof(num));n=0;}
void operator =(int x)
{
clr();
do
{
num[n++]=x%10000;
x/=10000;
}while(x);
}
BigInt operator /(const int &x)const
{
BigInt res;
res=(*this);
DOR(i,n-1,1)
{
res.num[i-1]+=(res.num[i]%x)*10000;
res.num[i]/=x;
}
res.num[0]/=x;
while(n>1&&res.num[res.n-1]==0)res.n--;
return res;
}
bool operator <(const BigInt &_)const
{
if(n!=_.n)return n<_.n;
DOR(i,n-1,0)if(num[i]!=_.num[i])return num[i]<_.num[i];
return false;
}
void operator *=(const int &x)
{
FOR(i,0,n-1)num[i]*=x;
FOR(i,0,n-1)
{
num[i+1]+=(num[i]/10000);
num[i]%=10000;
if(num[n])n++;
}
}
void Print()
{
printf("%d",num[n-1]);
DOR(i,n-2,0)printf("%04d",num[i]);
}
};
void chk_max(BigInt &x,BigInt y){if(x<y)x=y;}
int main()
{
scanf("%d",&n);
FOR(i,0,n)scanf("%d%d",&s[i].a,&s[i].b);
sort(s+1,s+1+n,cmp);
BigInt sum,ans;
sum=s[0].a,ans=0;
FOR(i,1,n)
{
chk_max(ans,sum/s[i].b);
sum*=s[i].a;
}
ans.Print();
return 0;
}