Luogu P3743 kotori的设备

题面

相对来说比较水的实数二分,但是这精度卡的。。。

废话不说,做法概要:

二分的部分就不说了,自己去实现,自己去卡精度

只说 check() 函数以及特殊处理

对于答案是 \(-1\) 的情况,只有一种情况,即:

\[\sum_{i=1}^n a_i \leq p \]

注意:计算 \(\sum_{i=1}^n a_i\) 的值时要用 double 不然你会挂得很惨

输入时特判即可

check() 函数

显然,以 \(k\) ,即使用时间作为二分对象,将 \(k\) 传入 check

只要充电总和大于或等于用电总和就返回真,否则返回假

用公式来表示就是这个样子(返回true的情况):

\[p \times k+\sum_{i=1}^n b_i-a_i\times k \geq 0 \]

细节:\(b_i-a_i\times k\) 必须保证小于 \(0\) 的情况时累加,即电池用完后才加

\(1\) ~ \(n\) 循环一下即可,为了提升效率,可在循环过程中直接判断

给出代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000+7;
int n,p;
int a[maxn],b[maxn];
inline bool check(double k) {
	double tmp = k * (double)p;
	for(int i=1;i<=n;++i) {
		double f = (double)b[i] - (double)a[i]*k;
		if(tmp < -f && f<0) return false;
		else if(f<0) tmp += f;
	}
	return true;
}
int main() {
	scanf("%d%d",&n,&p);
	double tmp = 0;                       // 某人用了int,他傻傻的看着90分15分钟
	for(int i=1;i<=n;++i) scanf("%d%d",a+i,b+i),tmp += a[i];
	if(tmp <= p) return printf("-1"),0;
	double l = 0,r = 1e10,mid;
	while(r - l >= 1e-6) {                // 1e-7 被 T
		mid = (l+r) / 2;
		if(check(mid)) l = mid;
		else r = mid;
	}
	printf("%.10lf",l);
	return 0;
}
posted @ 2020-04-01 00:13  AxDea  阅读(101)  评论(0编辑  收藏  举报