zoukankan      html  css  js  c++  java
  • AcWing 114.国王游戏

    题目传送门(Luogu)

    题目传送门(AcWing)

    一、公式推导

    我们对于国王身后的两个点来分析

    队列可能是这样的:

    (*) 左手 右手
    国王 (a_0) (b_0)
    (p1) (a_1) (b_1)
    (p2) (a_2) (b_2)

    根据题意:每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

    那么我们计算可得当前情况下大臣的最大金币数量: (large ans_1=max(frac{a_0}{b_1},frac{a_0*a_1}{b_2}))

    队列也有可能是这样的

    (*) 左手 右手
    国王 (a_0) (b_0)
    (p2) (a_2) (b_2)
    (p1) (a_1) (b_1)

    那么我们计算可得 (large ans_2=max(frac{a_0}{b_2},frac{a_0*a_2}{b_1}))

    我们来对比一下两个答案:
    (large ans_1=max(frac{a_0}{b_1},frac{a_0 * a_1}{b_2}))

    (large ans_2=max(frac{a_0}{b_2},frac{a_0 * a_2}{b_1}))


    (large k_1=frac{a_0}{b_1})
    (large k_2=frac{a_0 * a_1}{b_2})
    (large k_3=frac{a_0}{b_2})
    (large k_4=frac{a_0 * a_2}{b_1})

    因为(a_0*a_1>a_0),所以 (frac{a_0 * a_1}{b_2}>frac{a_0}{b_2}),即 (k_2>k_3)

    因为(a_0*a_2>a_0),所以 (frac{a_0 * a_2}{b_1}>frac{a_0}{b_1}),即 (k_4>k_1)

    如果想要 (ans_1<ans_2),那么 (max(k_1,k_2) < max(k_3,k_4)),因为上面已经知道(k_2>k_3), 所以 $k_4 > k_2 $

    即: (frac{a_0 * a_2}{b_1}> frac{a_0 * a_1}{b_2})

    不等式变型

    (a_0 * a_2 * b_2 > a_0 * a_1 * b_1)

    消去(a_0)

    (a_2 * b_2 > a_1 * b_1)

    也就是:
    (a_1 * b_1 < a_2 * b_2)

    也就是说,当 (a_1 * b_1 < a_2 * b_2)时,可以得到 (ans_1 <ans_2),也就是为了使(ans)更小,需要将(a_i * b_i)较小的放在前面,我们以(a_i * b_i)为关键字排序即可。

    同时,由于数据范围是:
    (n=1000),同时 (a<=10000),连乘就是 (1000)(10000)相乘,需要用到高精度。

    二、简单版本代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 10010;
    typedef long long LL;
    struct Person {
        int left, right;
    } person[N];
    int n;
    
    bool cmp(const Person &a, const Person &b) {
        return a.left * a.right < b.left * b.right;
    }
    
    int main() {
        cin >> n;
        //输入
        for (int i = 0; i <= n; i++)
            cin >> person[i].left >> person[i].right;
        //排序,注意国王不参加排序
        sort(person + 1, person + 1 + n, cmp);
    
        LL lcj = 1;//连乘积
        LL res = 0;
        for (int i = 0; i <= n; i++) {
            //猴子选大王
            res = max(res, lcj / person[i].right);
            //更新连乘各
            lcj *= person[i].left;
        }
        printf("%d", res);
        return 0;
    }
    

    三、高精度版本代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    int n;
    struct Person {
        int left, right;
    } person[N];
    
    bool cmp(const Person &a, const Person &b) {
        return a.left * a.right < b.left * b.right;
    }
    
    //高精度乘法
    vector<int> mul(vector<int> &A, int b) {
        vector<int> C;
        int t = 0;
        for (int i = 0; i < A.size() || t; i++) {
            if (i < A.size()) t += A[i] * b;
            C.push_back(t % 10);
            t /= 10;
        }
        while (C.size() > 1 && C.back() == 0) C.pop_back();
        return C;
    }
    
    //高精度除法
    vector<int> div(vector<int> &A, int b, int &r) {
        vector<int> C;
        r = 0;
        for (int i = A.size() - 1; i >= 0; i--) {
            r = r * 10 + A[i];
            C.push_back(r / b);
            r %= b;
        }
        reverse(C.begin(), C.end());
        while (C.size() > 1 && C.back() == 0) C.pop_back();
        return C;
    }
    
    //获取两个vector<int>中较大的那个
    vector<int> max_vec(vector<int> a, vector<int> b) {
        if (a.size() > b.size()) return a;
        if (a.size() < b.size()) return b;
        for (int i = a.size() - 1; i >= 0; i--) {
            if (a[i] > b[i]) return a;
            if (a[i] < b[i]) return b;
        }
        return a;
    }
    
    int main() {
        //优化输入
        ios::sync_with_stdio(false);
        cin >> n;
        //输入
        for (int i = 0; i <= n; i++)
            cin >> person[i].left >> person[i].right;
    
        //排序,国王不参加排序
        sort(person + 1, person + n + 1, cmp);
    
        //连乘各放入国王
        vector<int> lcj;
        lcj.push_back(person[0].left);
    
        //结果
        vector<int> res;
        res.push_back(0);//在做高精度时,也需要进行一步初始化
    
        for (int i = 1; i <= n; i++) {
            int r;//余数,本题中因为只需要下取整,所以余数无意义
            res = max_vec(res, div(lcj, person[i].right, r));
            lcj = mul(lcj, person[i].left);
        }
        //倒序输出高精度数组中的值
        for (int i = res.size() - 1; i >= 0; i--)
            printf("%d", res[i]);
        return 0;
    }
    
    
  • 相关阅读:
    电脑进入bios和u盘启动快捷键
    Securecrt 在win7下 字体太少问题
    windows无法安装到这个磁盘 gpt分区形式
    优酷上传高清视频
    将文件服务器及域控制器从2003迁移至Windows Server 2008 R2
    L SERVER 数据库被标记为“可疑”的解决办法
    Outlook关闭时最小化
    windows 7系统封装总结
    查询某软件所连接的外网IP地址
    windows桌面图标及任务管理栏丢失
  • 原文地址:https://www.cnblogs.com/littlehb/p/15038424.html
Copyright © 2011-2022 走看看