这道题我们一看数据范围,就觉得不简单,事实上我们这样想:
- 对于两个大臣来说,他们的先后顺序会对他们彼此得到的金币做出贡献对吧,那我们可以把他们看作一个大臣,对他们内部进行处理,然后其它的依次如此,也就是说我们可以只判断两位大臣相互的先后顺序,然后排序后得到最后的结果,即可得到我们想要的最小的最大值。
- 处理时我们可以有两人的价值得
- ans1 a n s 1 = max(a0b1,a0∗a1b2) m a x ( a 0 b 1 , a 0 ∗ a 1 b 2 )
- ans2 a n s 2 = max(a0b2,a0∗a2b1) m a x ( a 0 b 2 , a 0 ∗ a 2 b 1 )
- 由此我们又可以经过一系列转化得到
- a0∗a2b1 a 0 ∗ a 2 b 1 > a0∗a1b2 a 0 ∗ a 1 b 2
- 所以,为了
ans
a
n
s
取到最小值,我们需要将
ai∗bi
a
i
∗
b
i
较小的放在前面,这便是排序的依据
代码:
#include<bits/stdc++.h>
int n,l=1,a[100010],left[100010],right[100010],g[1000010];
void cheng(int x){
for(int i=1;i<=l;i++)
g[i]*=left[x];
for(int i=1;i<=l;i++) {
g[i+1]+=(g[i]/10);
g[i]%=10;
}
l++;
while(g[l]>9){
g[l+1]+=(g[l]/10);
g[l]%=10;
l++;
}
if(g[l]==0)
l--;
}
void chu(){
for(int i=l;i>=1;i--) {
g[i-1]+=((g[i]%right[n])*10);
g[i]/=right[n];
}
while(g[l]==0)
l--;
if(l==0)
printf("1\n");
}
void qsort(int l,int r) {
int i=l,j=r,mid=a[(l+r)/2];
while(i<=j) {
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j) {
int t=a[i];
a[i]=a[j];
a[j]=t;
t=left[i];
left[i]=left[j];
left[j]=t;
t=right[i];
right[i]=a[j]; //这里我为什么没用swap代替是因为我用swap居然报错了
right[j]=t; //懒得找原因所以就这样吧
i++;
j--;
}
}
if(l<j)
qsort(l,j);
if(i<r)
qsort(i,r);
}
int main() {
scanf("%d",&n);
scanf("%d%d",&left[0],&right[0]);
for(int i=1;i<=n;i++) {
scanf("%d%d",&left[i],&right[i]);
a[i]=left[i]*right[i]; //预先处理
}
qsort(1,n);
g[1]=left[0];
for(int i=1;i<n;i++)
cheng(i);
chu();
for(int i=l;i>=1;i--)
printf("%d",g[i]);
return 0;
}
另外,当我看到这道题是求最大值的最小值时,我第一点想到的是归并排序,同上面最初的结论,我们可以发现当前的归并时的顺序不管怎么排,这段序列之前的所有值对这一段的贡献是相同的,这段序列对之后的所有值的贡献也是相同的,也就是说我们似乎可以用归并排序的思想来对整段进行排序,当然博主也进行了尝试,不用高精度时过掉了所有不用高精度的点,然后也是因为懒,所以如果有兴趣的同学可以自己写个高精度进行优化,结果应该是对的,下面是归并的60分的代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
struct q{
ll left;
ll right;
}a[1005],b[1005];
ll n;
void Search(ll l,ll r){
if(l==r) return;
ll mid=(l+r)>>1;
Search(l,mid);
Search(mid+1,r);
ll nowl=l;
ll nowr=mid+1;
ll nowva=1;
ll now=0;
while(nowl<=mid&&nowr<=r){
if( ((nowva*a[nowl].left)/a[nowr].right)>
((nowva*a[nowr].left)/a[nowl].right) ){
b[l+now].left=a[nowr].left;
b[l+now].right=a[nowr].right;
nowva+=a[nowr].left;
now++;
nowr++;
}
else{
b[l+now].left=a[nowl].left;
b[l+now].right=a[nowl].right;
nowva+=a[nowl].left;
now++;
nowl++;
}
}
while(nowl<=mid){
b[l+now].left=a[nowl].left;
b[l+now].right=a[nowl].right;
nowva+=a[nowl].left;
now++;
nowl++;
}
while(nowr<=r){
b[l+now].left=a[nowr].left;
b[l+now].right=a[nowr].right;
nowva+=a[nowr].left;
now++;
nowr++;
}
for(int i=l;i<=r;i++){
a[i].left=b[i].left;
a[i].right=b[i].right;
}
return;
}
int main()
{
// freopen("game.in","r",stdin);
// freopen("game.out","w",stdout);
scanf("%lld",&n);
for(int i=0;i<=n;i++)
scanf("%lld%lld",&a[i].left,&a[i].right);
Search(1,n);
ll now=a[0].left;
ll Max=0;
for(int i=1;i<=n;i++){
Max=max(Max,now/a[i].right);
now*=a[i].left;
}
printf("%lld",Max);
return 0;
}