>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();
}