链接
题目描述
现在有n人,每个人有一个左值和右值,他们排成一个序列,每个人的中值=排在他前面的所有人的左值乘积除以他自己的右值,现在你可以修改除了第一个人之外的人的位置,使得序列中最大中值最小
样例输入
3
1 1
2 3
7 4
4 6
样例输出
2
思路
考虑邻项交换
交换前 | 交换后 | |
---|---|---|
第i个人 | S i − 1 b i \frac{S_{i-1}}{b_i} biSi−1 | S i − 1 b i + 1 \frac{S_{i-1}}{b_{i+1}} bi+1Si−1 |
第i+1个人 | S i − 1 ∗ a i b i + 1 \frac{S_{i-1} * a_i}{b_{i + 1}} bi+1Si−1∗ai | S i − 1 ∗ a i + 1 b i \frac{S_{i-1}*a_{i+1}}{b_i} biSi−1∗ai+1 |
那也就是比较式子大小就可以了
m
a
x
(
S
i
−
1
b
i
,
S
i
−
1
∗
a
i
b
i
+
1
)
m
a
x
(
S
i
−
1
b
i
+
1
,
S
i
−
1
∗
a
i
+
1
b
i
)
max(\frac{S_{i-1}}{b_i},\frac{S_{i-1} * a_i}{b_{i + 1}}) \ max(\frac{S_{i-1}}{b_{i+1}},\frac{S_{i-1}*a_{i+1}}{b_i})
max(biSi−1,bi+1Si−1∗ai) max(bi+1Si−1,biSi−1∗ai+1)
内部除以
S
i
−
1
S_{i-1}
Si−1
得到:
m
a
x
(
1
b
i
,
a
i
b
i
+
1
)
m
a
x
(
1
b
i
+
1
,
a
i
+
1
b
i
)
max(\frac{1}{b_i},\frac{a_i}{b_{i + 1}}) \ \ \ max(\frac{1}{b_{i+1}},\frac{a_{i+1}}{b_i})
max(bi1,bi+1ai) max(bi+11,biai+1)
内部乘上
b
i
∗
b
i
+
1
b_i * b_{i+1}
bi∗bi+1,得
m
a
x
(
b
i
+
1
,
a
i
∗
b
i
)
m
a
x
(
b
i
,
a
i
+
1
b
i
+
1
)
max(b_{i+1},a_i*b_i) \ \ \ max(b_{i},a_{i+1}{b_{i+1}})
max(bi+1,ai∗bi) max(bi,ai+1bi+1)
那很容易得到结论
若有
i
i
i使得
a
i
∗
b
i
≥
a
i
+
1
∗
b
i
+
1
a_i*b_i \geq a_{i+1} * b_{i+1}
ai∗bi≥ai+1∗bi+1
那么我们就可以交换第
i
i
i个人与第
i
+
1
i+1
i+1个人
那么我们把所有人按
a
i
∗
b
i
a_i * b_i
ai∗bi从小到大排序即可
别忘高精
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
ll n, kl, kr;
struct GJ
{
ll l;
ll a[10005];
}ans, S;
struct qwq
{
ll l, r;
ll sum;
}a[10005];
bool cmp(qwq a, qwq b)
{
return a.sum < b.sum;
}
GJ operator /(GJ x, int y)
{
for(int i = x.l - 1; i >= 1; --i)
{
x.a[i - 1] += x.a[i] % y * 10;
x.a[i] /= y;
if(!x.a[i] && i == x.l - 1) x.l--;
}
x.a[0] = x.a[0] / y;
return x;
}//高精除
GJ operator *(GJ x, int y)
{
ll add = 0;
for(int i = 0; i < x.l; ++i)
{
x.a[i] *= y;
x.a[i] += add;
add = x.a[i] / 10;
x.a[i] %= 10;
}
x.a[x.l] += add;
while(x.a[x.l])
{
x.l++;
x.a[x.l] = x.a[x.l - 1] / 10;
x.a[x.l - 1] %= 10;
}
return x;
}//高精乘
bool operator <(GJ x, GJ y)
{
if(x.l != y.l) return x.l < y.l;
for(int i = x.l - 1; i >= 0; --i)
if(x.a[i] != y.a[i])
return x.a[i] < y.a[i];
return 0;
}
int main()
{
scanf("%lld%lld%lld", &n, &kl, &kr);
for(int i = 1; i <= n; ++i)
{
scanf("%lld%lld", &a[i].l, &a[i].r);
a[i].sum = a[i].l * a[i].r;
}
sort(a + 1, a + n + 1, cmp);
S.a[0] = kl; S.l = 1;
for(int i = 1; i <= n; ++i)
{
if(ans < S / a[i].r)
ans = S / a[i].r;
S = S * a[i].l;
}
printf("%lld", ans.a[ans.l - 1]);
for(int i = ans.l - 2; i >= 0; --i) printf("%lld", ans.a[i]);
}