题解:P1080 [NOIP2012 提高组] 国王游戏
其实不用推那么多,邻项交换放弃大脑。
我直接在 cmp 中比较两者两种排序的权值,取较小的一种即可。
我令前面的乘积是 \(s\),则:
-
如果不换,那么权值是 \(\displaystyle \max(\frac{s}{r_1}, \frac{s \times l_1}{r_2})\)。
-
如果换,那么权值是 \(\displaystyle \max(\frac{s}{r_2}, \frac{s \times l_2}{r_1})\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
struct node {
int l, r;
}a[N];
bool cmp(node a, node b) {
return max(1.0 / (double)a.r, (double)a.l / b.r) < max(1.0 / (double)b.r, (double)b.l / a.r);
}
struct Num {
int num[50005];
int len;
void init(int x) {
while(x) {
num[ ++ len] = x % 100000;
x /= 100000;
}
}
Num operator * (const int a) const {
Num res;
for(int i = 1;i <= len;i ++ ) {
res.num[i] = a * num[i];
}
for(int i = 1;i <= len;i ++ ) {
res.num[i + 1] += res.num[i] / 100000;
res.num[i] %= 100000;
}
res.len = len;
while(res.num[res.len + 1] != 0) {
res.num[res.len + 1] += res.num[res.len] / 100000;
res.num[res.len] %= 100000;
res.len ++ ;
}
return res;
}
Num operator / (const int a) const {
Num res;
long long cur = 0;
for(int i = len;i >= 1;i -- ) {
cur = cur * 100000 + num[i];
res.num[i] = cur / a;
cur %= a;
}
res.len = len;
while(res.num[res.len] == 0) res.len -- ;
return res;
}
bool operator < (const Num a) const {
if(len > a.len) return 0;
if(len < a.len) return 1;
for(int i = len;i >= 1;i -- ) {
if(num[i] > a.num[i]) return 0;
if(num[i] < a.num[i]) return 1;
}
return 1;
}
};
int main() {
int n, x, y;
cin >> n;
cin >> x >> y;
for(int i = 1;i <= n;i ++ ) {
cin >> a[i].l >> a[i].r;
}
/*
相邻的两个大臣 l1, r1, l2, r2, 令前面的乘积为 s
max(1 / r1, l1 / r2), max(1 / r2, l2 / r1)
如果不交换是最优的, 则
1. 1 / r1 < 1 / r2
则 1 / r2 > l2 / r1
又 l2 / r1 > 1 / r1
则 1 / r2 > 1 / r1 恒成立
2. 1 / r1 < l2 / r1 恒成立
3. l1 / r2 < 1 / r2 无解(不可能出现)
4. l1 / r2 < l2 / r1
*/
sort(a + 1, a + n + 1, cmp);
Num ans, cur;
ans.init(0);
cur.init(x);
for(int i = 1;i <= n;i ++ ) {
ans = max(ans, cur / a[i].r);
cur = cur * a[i].l;
}
printf("%d", ans.num[ans.len]);
for(int i = ans.len - 1;i >= 1;i -- ) {
printf("%05d", ans.num[i]);
}
return 0;
}

浙公网安备 33010602011771号