国王游戏与皇后游戏

国王游戏

首先,每个人在左、右手上面分别有一个整数。然后, N N N位大臣排成一排,国王站在队伍的最前面。每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
现在要使金币的最大值最小


可以来试着推一下
先把关系设好
假设加上国王只有下面三个人(大臣 M i n i s t e r Minister Minister M M M表示,金币用 C C C

左手右手
K i n g King King a 0 a_0 a0 b 0 b_0 b0
M 1 M1 M1 a 1 a_1 a1 b 1 b_1 b1
M 2 M2 M2 a 2 a_2 a2 b 2 b_2 b2

这个 m a r k d o w n markdown markdown编辑器不支持多行等式的样子,只好用图片
当前答案:

两位大臣交换后:

假设不交换更优
那么 m a x ( a 0 b 2 , a 0 ∗ a 2 b 1 ) > m a x ( a 0 b 1 , a 0 ∗ a 1 b 2 ) max(\frac{a_0}{b_2},\frac{a_0*a_2}{b_1})>max(\frac{a_0}{b_1},\frac{a_0*a_1}{b_2}) max(b2a0,b1a0a2)>max(b1a0,b2a0a1)
设这四项分别为 A , B , C , D A,B,C,D A,B,C,D
显然 B > C , D > A B>C,D>A B>C,D>A
又有 m a x ( A , B ) > m a x ( C , D ) max(A,B)>max(C,D) max(A,B)>max(C,D)
这个 A A A是随便插空都可以的
但可知 D D D一定大于 B B B
a 0 ∗ a 2 b 1 > a 0 ∗ a 1 b 2 \frac{a_0*a_2}{b_1}>\frac{a_0*a_1}{b_2} b1a0a2>b2a0a1
所以 a 2 b 1 > a 1 b 2 \frac{a_2}{b_1}>\frac{a_1}{b_2} b1a2>b2a1
得出不等式 a 1 ∗ b 1 &lt; a 2 ∗ b 2 a_1*b_1&lt;a_2*b_2 a1b1<a2b2
结论 − &gt; -&gt; > a ∗ b a*b ab从小到大排序会使答案更优
国王游戏就是这样
比较简单
But要高精
传送门
代码:

#include <iostream>
#include <complex>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
namespace BigInteger {
    struct Big_integer {
        int d[10005], len;
        void clean() {while(len > 1 and !d[len - 1]) len--;}
        Big_integer() {memset(d, 0, sizeof d); len = 1;}
        Big_integer(int num) {*this = num;}
        Big_integer operator = (const char* num) {
            memset(d, 0, sizeof d);
            len = strlen(num);
            for (int i = 0; i < len; i++) d[i] = num[len - 1 - i] - '0';
            clean();
            return *this;
        }
        Big_integer operator = (int num) {
            char s[10005];
            sprintf(s, "%d", num);
            *this = s;
            return *this;
        }
        Big_integer operator * (const Big_integer &b) const {
            int i, j;
            Big_integer c;
            c.len = len + b.len;
            for (j = 0; j < b.len; j++)
              for (i = 0; i < len; i++)
                c.d[i + j] += d[i] * b.d[j];
            for (i = 0; i < c.len - 1; i++) {
                c.d[i + 1] += c.d[i] / 10;
                c.d[i] %= 10;
            }
            c.clean();
            return c;
        }
        Big_integer operator / (const int &b) {
            int i, j, a = 0;
            Big_integer c = *this;
            for (i = len - 1; i >= 0; i--) {
                a = a * 10 + d[i];
                for (j = 0; j < 10; j++)
                  if (a < b * (j + 1)) break;
                c.d[i] = j;
                a = a - b * j;
            }
            c.clean();
            return c;
        }
        bool operator < (const Big_integer &b) const {
            if (len != b.len) return len < b.len;
            for (int i = len - 1; i >= 0; i--)
                if (d[i] != b.d[i])
                    return d[i] < b.d[i];
            return false;
        }
        string str() const {
            char s[10005];
            for (int i = 0; i < len; i++) s[len - 1 - i] = d[i] + '0';
            return s;
        }
    };
    istream& operator >> (istream& in, Big_integer &x) {
        string s;
        in >> s;
        x = s.c_str();
        return in;
    }
    ostream& operator << (ostream& out, const Big_integer &x) {
        out << x.str();
        return out;
    }
}
using namespace BigInteger;
struct node {
    int a, b;
    friend bool operator < (const node x, const node y) {
        return x.a * x.b < y.a * y.b;
    }
}e[10010];
int n;
Big_integer ans, tmp = 1;

int main(int argc, char const *argv[]) {
    scanf("%d%d%d", &n, &e[1].a, &e[1].b);
    for (int i = 2; i <= n + 1; i++) scanf("%d%d", &e[i].a, &e[i].b);
    sort(e + 2, e + n + 2);
    for (int i = 2; i <= n + 1; i++) {
        tmp = tmp * e[i - 1].a;
        ans = max(ans, tmp / e[i].b);
    }
    cout << ans << endl;
}

再看少麻烦点的皇后游戏




皇后游戏

皇后有 N N N位大臣,每位大臣的左右手上面分别写上了一个正整数。要为 N N N位大臣颁发奖金,其中第 i i i位大臣所获得的奖金数目
为第 i − 1 i-1 i1位大臣所获得奖金数目与前 i i i位大臣左手上的数的和的较大值再加上第 i i i位大臣右手上的数
即:设第 i i i位大臣左手上的正整数为 a i a_i ai,右手上的正整数为 b i b_i bi,则第 i i i位大臣获得的奖金数目为 C i C_i Ci可以表达为:


可以仿照着国王游戏自己yy一下
来看怎么做
我们还是假设两个大臣编号为 i i i j j j
C i − 1 = Y , ∑ k = 1 i − 1 a k = X C_{i-1}=Y,\sum_{k=1}^{i-1} a_k=X Ci1=Y,k=1i1ak=X
则当前答案为:

交换两位大臣的位置后:

假设交换更优
那么第二个等式大于第一个等式
发现两边都有 Y + b i + b j Y+b_i+b_j Y+bi+bj,消去:
m a x ( X + a j + b i + b j , X + a i + a j + b i ) &gt; m a x ( X + a i + b i + b j , X + a i + a j + b j ) max(X+a_j+b_i+b_j,X+a_i+a_j+b_i)&gt;max(X+a_i+b_i+b_j,X+a_i+a_j+b_j) max(X+aj+bi+bj,X+ai+aj+bi)>max(X+ai+bi+bj,X+ai+aj+bj)
再把共同的 X X X提出来:
m a x ( a j + b i + b j , a i + a j + b i ) &gt; m a x ( a i + b i + b j , a i + a j + b j ) max(a_j+b_i+b_j,a_i+a_j+b_i)&gt;max(a_i+b_i+b_j,a_i+a_j+b_j) max(aj+bi+bj,ai+aj+bi)>max(ai+bi+bj,ai+aj+bj)
把两边分别共有的拿出来:
m a x ( b j , a i ) + a j + b i &gt; m a x ( b i , a j ) + a i + b j max(b_j,a_i)+a_j+b_i&gt;max(b_i,a_j)+a_i+b_j max(bj,ai)+aj+bi>max(bi,aj)+ai+bj
移项:
m a x ( b j , a i ) − a i − b j &gt; m a x ( b i , a j ) − a j − b i max(b_j,a_i)-a_i-b_j&gt;max(b_i,a_j)-a_j-b_i max(bj,ai)aibj>max(bi,aj)ajbi
可知两个中大的会被减掉然后剩下小的那个的相反数
− m i n ( b i , a i ) &gt; − m i n ( b j , a j ) -min(b_i,a_i)&gt;-min(b_j,a_j) min(bi,ai)>min(bj,aj)
最后得到: m i n ( a i , b j ) &lt; m i n ( a j , b i ) min(a_i,b_j)&lt;min(a_j,b_i) min(ai,bj)<min(aj,bi)
又是一个简单式子
I n t e r e s t i n g Interesting Interesting

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良月澪二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值