题目描述
有 n n n 瓶溶液,每瓶溶液体积为 a a a,浓度为 b b b,现在从每瓶中取一些溶液(也可以不选)混合成浓度为 m m m 的溶液,问浓度为 m m m 的溶液体积最大为多少。
输入格式
第一行一个整数
n
n
n,表示溶液的瓶数。
第二行
n
n
n 个整数
b
i
b_i
bi,表示每瓶溶液的浓度。
第三行
n
n
n 个整数
a
i
a_i
ai,表示每瓶溶液的体积。
第四行一个整数
m
m
m,表示需要混合成的浓度。
输出格式
输出一个小数(保留 5 5 5 位)表示最大的体积。
数据范围
1
≤
n
≤
10000
1 \le n \le 10000
1≤n≤10000
1
≤
a
≤
1000
1 \le a \le 1000
1≤a≤1000
1
≤
b
≤
500
1 \le b \le 500
1≤b≤500
样例
样例输入1
3
50 50 50
395 971 964
50
样例输出1
2330.00000
样例输入2
4
3 5 6 2
9 12 20 18
4
样例输出2
55.50000
题解
由于要是体积最大,我们可以先把所有溶液倒在一起,计算出体积 x x x 和 浓度和体积的乘积 y y y。
for(int i = 1; i <= n; ++ i){
x += x[i].a;
}
for(int i = 1; i <= n; ++ i){
y += x[i].a * x[i].b;
}
然后比较 x y \frac{x}{y} yx 和 m m m,有以下几种情况:
- x y \frac{x}{y} yx 等于 m m m。
- x y \frac{x}{y} yx 小于 m m m。
- x y \frac{x}{y} yx 大于 m m m。
对于第一种情况,此时体积最大,直接输出。
对于第二种情况,应该从最小浓度的溶液开始倒,直到 x y \frac{x}{y} yx 大于等于 m m m 为止。
- 如果 x y \frac{x}{y} yx 等于 m m m,直接输出当前的体积。
- 如果 x y \frac{x}{y} yx 大于 m m m,将当前这瓶倒的体积进行实数二分,计算出体积。也可以推导数学公式。
p 表示当前这瓶的编号
double l = 0, r = x[p].a;
while(r - l > 1e-10){
double mid = (l + r) / 2;
if(check2(mid, p)){//check2 判断加上 p 瓶 mid 的浓度是否大于 m,大于返回 0
r = mid;
}
else{
l = mid;
}
}
sum += l;
对于第三种情况,也是同理。
代码
//要开 long long
bool check(double o, int y){//check 判断加上 p 瓶 mid 的浓度是否大于 m,小于返回 1
double t = (u + o * x[y].b) / (sum + o);
if(t - m < 1e-10){
return 1;
}
return 0;
}
bool check2(double o, int y){//check2 判断加上 p 瓶 mid 的浓度是否大于 m,大于返回 0
double t = (u + o * x[y].b) / (sum + o);
if(t - m > 1e-10){
return 0;
}
return 1;
}
int main(){
输入,并计算 u 和 sum
if(u / sum > m){//浓度大于 m
浓度从大到小排序
int p = 0;
//从最大的开始,依次倒掉,直到浓度小于 m
while(u / sum > m && p < n){
sum -= x[++ p].a;
u -= x[p].a * x[p].b;
}
if(u / sum < m){
double l = 0, r = x[p].a, ans = 0;
while(r - l > 1e-10){
double mid = (l + r) / 2;
if(check(mid, p)){
l = mid;
}
else{
r = mid;
}
}
sum += l;
}
}
else if(u / sum < m){//浓度小于 m
浓度从小到大排序
int p = 0;
//从最小的开始,依次倒掉,直到浓度大于 m
while(u / sum < m && p < n){
sum -= x[++ p].a;
u -= x[p].a * x[p].b;
}
if(u / sum > m){
double l = 0, r = x[p].a;
while(r - l > 1e-10){
double mid = (l + r) / 2;
if(check2(mid, p)){
r = mid;
}
else{
l = mid;
}
}
sum += l;
}
}
输出
return 0;
}