国王游戏
首先,每个人在左、右手上面分别有一个整数。然后,
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,b1a0∗a2)>max(b1a0,b2a0∗a1)
设这四项分别为
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}
b1a0∗a2>b2a0∗a1
所以
a
2
b
1
>
a
1
b
2
\frac{a_2}{b_1}>\frac{a_1}{b_2}
b1a2>b2a1
得出不等式
a
1
∗
b
1
<
a
2
∗
b
2
a_1*b_1<a_2*b_2
a1∗b1<a2∗b2
结论
−
>
->
−>按
a
∗
b
a*b
a∗b从小到大排序会使答案更优
国王游戏就是这样
比较简单
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
i−1位大臣所获得奖金数目与前
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
Ci−1=Y,∑k=1i−1ak=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
)
>
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)>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
)
>
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)>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
>
m
a
x
(
b
i
,
a
j
)
+
a
i
+
b
j
max(b_j,a_i)+a_j+b_i>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
>
m
a
x
(
b
i
,
a
j
)
−
a
j
−
b
i
max(b_j,a_i)-a_i-b_j>max(b_i,a_j)-a_j-b_i
max(bj,ai)−ai−bj>max(bi,aj)−aj−bi
可知两个中大的会被减掉然后剩下小的那个的相反数
即
−
m
i
n
(
b
i
,
a
i
)
>
−
m
i
n
(
b
j
,
a
j
)
-min(b_i,a_i)>-min(b_j,a_j)
−min(bi,ai)>−min(bj,aj)
最后得到:
m
i
n
(
a
i
,
b
j
)
<
m
i
n
(
a
j
,
b
i
)
min(a_i,b_j)<min(a_j,b_i)
min(ai,bj)<min(aj,bi)
又是一个简单式子
I
n
t
e
r
e
s
t
i
n
g
Interesting
Interesting