[P3743] kotori的设备 题解
今天做的第三道二分的题目。这次是在实数域上二分,犯了很多不必要的错误www
在实数域上二分要预先确定好精度 \(eps\) 。在这道题上,\(eps\le 10^{-5}\) 比较保险。
我们还是考虑二分答案。对于每一个二分到的答案,我们这样判定合法性:
- 若设备已有的能量可以满足目前答案需要,忽略该设备。
- 若设备已有的能量不能满足目前答案需要,那就用充电器充电到刚好满足为止。
- 比较需要的能量总和和充电器最多提供的能量,没超过就合法,超过了就不合法。
所有设备的消耗能量速度总和小于充电器的充电速度,输出 \(-1\)。
时间复杂度 O(n \log k) 。其中 \(k\) 是一个很大的数字。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = 1e-5;
const int maxn = 1000005;
typedef double db;
int n;
double p, sum = 0;
db a[maxn], b[maxn];
bool check(db ans) {
db maxx = p * ans;
db real = 0.0;
for(int i = 1; i <= n; i ++) {
if(a[i] * ans <= b[i]) continue;
real += a[i] * ans - b[i];
} return real <= maxx;
}
int main() {
cin >> n >> p;
for(int i = 1; i <= n; i ++) {
cin >> a[i] >> b[i];
sum += a[i];
} if(sum <= p) return puts("-1") & 0;
double l = 0.0, r = 1e10, mid;
while(r - l > eps) {
mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
} printf("%.10lf", l);
}