题解
这题一开始我想歪了。对每个大臣而言,显然排在队尾是能拿到最多钱的,所以我以为只要考虑n个大臣排在队尾
的情况就足以覆盖最大的所有情况了。
问题是什么呢?就是我考虑的是每个大臣能拿到的最值情况,但并不是所有排列下,该排列的最值情况。
就是说在某种情形下,排在队尾的大臣确实拿到了比其他任何排列情况都要多的钱,但是他不是该排列下
的最值。
所以这道题其实是要找到一种能够让这个队列所有成员都拿到最小的排列方法。这个方法是存在的。
排序方法是 a1*b1 < a2*b2
为什么呢,可以举个2人的例子理解。
ps:这题其实必须要处理大数。后续代码中有大数的模版。
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100000;
int n,m;
struct minis{
int l,r,pd;
minis(){}
minis(int a,int b):l(a),r(b),pd(a*b){}
bool operator <(const minis &x)const{
return pd < x.pd;
}
}cot[1002];
struct BigInt{
int data[N];
BigInt(){
memset(data,0,sizeof(data));
data[0] = 1;
}
BigInt(int x){
memset(data,0,sizeof(data));
data[0] = 1;
int i=1;
while(x){
data[i++] = x % 10;
x/=10;
}
data[0] = --i;
}
BigInt operator *(const int &x){
BigInt a;
int len;
a.data[0] = data[0];
for(int i=1;i<=data[0];i++) a.data[i] = data[i]*x;
for(int i=1;i<=a.data[0] || a.data[i]; len = ++i){
a.data[i+1] +=a.data[i]/10;
a.data[i] %= 10;
}
a.data[len] ? a.data[0] = len : a.data[0] = --len;
return a;
}
BigInt operator /(const int &x){
BigInt a;
int rest = 0;
a.data[0] = data[0];
for(int i= data[0];i>=1;i--){
rest = rest*10 +data[i];
a.data[i] = rest / x;
rest %= x;
}
while(!a.data[ a.data[0] ] && a.data[0] > 1) a.data[0]--;
return a;
}
bool operator <(const BigInt &x)const{
if(data[0] == x.data[0]){
int i;
for(i=data[0];data[i] == x.data[i] && i>1;i--);
if( i>=1) return data[i] < x.data[i];
else return false;// equal
}
else return data[0] < x.data[0];
}
};
ostream& operator <<(ostream& out, const BigInt &x){
for(int i=1;i<=x.data[0];i++) out<<x.data[x.data[0] - i + 1];
return out;
}
int main(){
cin>>n;
int x,y;
for(int i=0;i<=n;i++){
cin>>x>>y;
cot[i] = minis(x,y);
}
sort(cot+1,cot+1+n);
BigInt k(1),tmp,ans;
for(int i=1;i<=n;i++){
if(cot[i-1].l==0) break;
k = k*cot[i-1].l;
tmp = k/cot[i].r ;
if(ans < tmp) ans = tmp;
}
cout<<ans<<endl;
return 0;
}