国王游戏

这里写图片描述

题目地址

这道题我们一看数据范围,就觉得不简单,事实上我们这样想:

  • 对于两个大臣来说,他们的先后顺序会对他们彼此得到的金币做出贡献对吧,那我们可以把他们看作一个大臣,对他们内部进行处理,然后其它的依次如此,也就是说我们可以只判断两位大臣相互的先后顺序,然后排序后得到最后的结果,即可得到我们想要的最小的最大值。
  • 处理时我们可以有两人的价值得
  • ans1 a n s 1 = max(a0b1,a0a1b2) m a x ( a 0 b 1 , a 0 ∗ a 1 b 2 )
  • ans2 a n s 2 = max(a0b2,a0a2b1) m a x ( a 0 b 2 , a 0 ∗ a 2 b 1 )
  • 由此我们又可以经过一系列转化得到
  • a0a2b1 a 0 ∗ a 2 b 1 > a0a1b2 a 0 ∗ a 1 b 2
  • 所以,为了 ans a n s 取到最小值,我们需要将 aibi 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值