>link
>解题思路
左手为
X
i
X_i
Xi,右手为
Y
i
Y_i
Yi
S
i
=
∏
j
=
1
i
x
i
S_i=\prod^i_{j=1}x_i
Si=j=1∏ixi
考虑相邻的两个大臣的交换
交换前 | 交换后 | |
---|---|---|
第 i i i个大臣 | S i − 1 Y i \frac{S_{i-1}}{Y_i} YiSi−1 | S i − 1 Y i + 1 \frac{S_{i-1}}{Y_{i+1}} Yi+1Si−1 |
第 i + 1 i+1 i+1个大臣 | S i − 1 ∗ X i Y i + 1 \frac{S_{i-1}*X_i}{Y_{i+1}} Yi+1Si−1∗Xi | S i − 1 ∗ X i + 1 Y i \frac{S_{i-1}*X_{i+1}}{Y_i} YiSi−1∗Xi+1 |
m
i
n
(
m
a
x
(
S
i
−
1
Y
i
,
S
i
−
1
∗
X
i
Y
i
+
1
)
,
m
a
x
(
S
i
−
1
Y
i
+
1
,
S
i
−
1
∗
X
i
+
1
Y
i
)
)
min(max(\frac{S_{i-1}}{Y_i},\frac{S_{i-1}*X_i}{Y_{i+1}}),max(\frac{S_{i-1}}{Y_{i+1}},\frac{S_{i-1}*X_{i+1}}{Y_i}))
min(max(YiSi−1,Yi+1Si−1∗Xi),max(Yi+1Si−1,YiSi−1∗Xi+1))
以下化简公式
两边除以
S
i
−
1
S_{i-1}
Si−1
m
i
n
(
m
a
x
(
1
Y
i
,
X
i
Y
i
+
1
)
,
m
a
x
(
1
Y
i
+
1
,
X
i
+
1
Y
i
)
)
min(max(\frac{1}{Y_i},\frac{X_i}{Y_{i+1}}),max(\frac{1}{Y_{i+1}},\frac{X_{i+1}}{Y_i}))
min(max(Yi1,Yi+1Xi),max(Yi+11,YiXi+1))
去分母,两边乘上
(
Y
i
)
(
Y
i
+
1
)
(Y_i)(Y_{i+1})
(Yi)(Yi+1)
m
i
n
(
m
a
x
(
Y
i
+
1
,
X
i
∗
Y
i
)
,
m
a
x
(
Y
i
,
X
i
+
1
∗
Y
i
+
1
)
)
min(max(Y_{i+1},X_i*Y_i),max(Y_i,X_{i+1}*Y_{i+1}))
min(max(Yi+1,Xi∗Yi),max(Yi,Xi+1∗Yi+1))
m
i
n
(
m
a
x
(
a
2
,
b
1
)
,
m
a
x
(
a
1
,
b
2
)
)
min(max(a2,b1),max(a1,b2))
min(max(a2,b1),max(a1,b2))
很容易发现
Y
i
<
X
i
∗
Y
i
Y_i<X_i*Y_i
Yi<Xi∗Yi
Y i + 1 < X i + 1 ∗ Y i + 1 Y_{i+1}<X_{i+1}*Y_{i+1} Yi+1<Xi+1∗Yi+1
= = =
a 1 < b 1 a1<b1 a1<b1
a
2
<
b
2
a2<b2
a2<b2
在有比较性的搭配中,只有最终
b
1
b1
b1和
b
2
b2
b2的比较
m
i
n
(
X
i
∗
Y
i
,
X
i
+
1
∗
Y
i
+
1
)
min(X_i*Y_i,X_{i+1}*Y_{i+1})
min(Xi∗Yi,Xi+1∗Yi+1)
那么就是任意的
X
i
∗
Y
i
X_i*Y_i
Xi∗Yi比
X
i
+
1
∗
Y
i
+
1
X_{i+1}*Y_{i+1}
Xi+1∗Yi+1小(不交换)的队伍是最优的
//(如果要交换的话,排出来的队伍就不是最优的)
也就是按照
X
∗
Y
X*Y
X∗Y从小到大的排序
S S S的最大数值是 100 0 10000 1000^{10000} 100010000,要高精度: )
>Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 10000;
struct DT {
int x, y, s;
} a[1010];
int n, ax, ay, s[maxn + 10], tpy[maxn + 10], ans[maxn + 10];
bool cmp(const DT& k, const DT& l) { return k.s < l.s; }
void cheng(int x) {//高精乘
int g = 0;
for (int i = maxn; i; i--) {
s[i] = s[i] * x + g;
g = s[i] / 10;
s[i] %= 10;
}
}
void chu(int x) {//高精除
memset(tpy, 0, sizeof(tpy));
long long g = 0;
int i = 1;
while (i <= maxn && s[i] == 0) i++;
for (; i <= maxn; i++) {
g = g * 10 + s[i];
if (g >= x) {
tpy[i] = g / x;
g %= x;
}
}
}
void replace(int x) {//更新max
for (int i = x; i <= maxn; i++) ans[i] = tpy[i];
}
void compare() {//比较当前max和当前大臣的奖励数
int i = 1;
while (i <= maxn && tpy[i] == 0) i++;//当前大臣的奖励数
int j = 1;
while (j <= maxn && ans[j] == 0) j++;//当前max
if (i < j)
replace(i);
for (; i <= maxn; i++, j++)
if (tpy[i] > ans[j]) {
replace(i);
return;
} else if (tpy[i] < ans[j])
return;
}
void print() {
int i = 1;
while (i <= maxn && ans[i] == 0) i++;
while (i <= maxn) {
printf("%d", ans[i]);
i++;
}
}
int main() {
scanf("%d%d%d", &n, &ax, &ay);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].x, &a[i].y);
a[i].s = a[i].x * a[i].y;
}
sort(a + 1, a + 1 + n, cmp);
s[maxn] = 1;
cheng(ax);//国王
for (int i = 1; i <= n; i++) {
chu(a[i].y);//算出当前大臣的奖励
compare();//比较max
cheng(a[i].x);//乘左手
}
print();
}