传送门:题目
题意:
一共有n个电器,一个充电宝,充电宝有无限电量,但是只有一个接口,也就是不能同时给两个电器充电,然后输出还有限,每秒钟输出p格电量(垃圾充电宝),然后告诉你每个电器每秒钟耗费几格电量a[i],以及每个电器电池的初始时剩余电量b[i],每个电器电池的容量是无限的,也就是充电宝不会把电器充爆。问你所有电器同时连续使用的最长时间,充电宝由一个电器换插到另一个电器不耗费时间。如果这个时间不存在,也就是所有电器可以一直工作,输出-1
题解:
题目很好理解,求两个电器同时没电的时刻。
第一种情况:
a[1]+a[2]+⋯+a[n]≤p
a
[
1
]
+
a
[
2
]
+
⋯
+
a
[
n
]
≤
p
,输出-1.
第二种情况:
a[1]+a[2]+⋯+a[n]>p
a
[
1
]
+
a
[
2
]
+
⋯
+
a
[
n
]
>
p
,我们可以这样理解,充电宝的输出效率小于电器的需求效率。
设我们要求的时刻是t,那么肯定有:
t∗p=sum(a[i]∗t−b[i])(i∈[1,n]且b[i]−a[i]∗t<0)
t
∗
p
=
s
u
m
(
a
[
i
]
∗
t
−
b
[
i
]
)
(
i
∈
[
1
,
n
]
且
b
[
i
]
−
a
[
i
]
∗
t
<
0
)
上面的公式很好理解,等式的左面是充电宝的输出量,等式的右边是电器需求量,注意小括号里的,如果初始电量足够大,不需要充电宝,我们就不用加这个电器了。
如何求t呢?我们可以二分一下:
如果
mid∗p<sum(a[i]∗mid−b[i])
m
i
d
∗
p
<
s
u
m
(
a
[
i
]
∗
m
i
d
−
b
[
i
]
)
,那么应该让电池再多输出一点,
l=mid
l
=
m
i
d
如果
mid∗p>sum(a[i]∗mid−b[i])
m
i
d
∗
p
>
s
u
m
(
a
[
i
]
∗
m
i
d
−
b
[
i
]
)
,那么应该让电池再少输出一点,
r=mid
r
=
m
i
d
AC代码:
#include <iostream>
#include <cstring>//字符串
#include <cstdio>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 10;
const double EPS = 1e-4;
int n, p, a[maxn], b[maxn];
bool check(double time) {
double sum = 0.0;
for (int i = 0; i < n; i++)
if (b[i] - a[i]*time < 0)
sum += a[i] * time - b[i];
return time * p > sum;
}
int main(void) {
cin >> n >> p;
long long sum = 0;
for (int i = 0; i < n; i++)
cin >> a[i] >> b[i], sum += a[i];
if (sum <= p)
return 0 * puts("-1");
double l = 0, r = 1e18;
double mid = (l + r) / 2;
while (r - l >= EPS) {
if (check(mid))
l = mid;
else
r = mid;
mid = (l + r) / 2;
}
cout << r << endl;
return 0;
}