码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P3743 kotori的设备

时间:2020-04-01 00:42:03      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:return   line   就是   clu   www   cpp   print   ble   必须   

题面

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

废话不说,做法概要:

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

只说 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;
}

Luogu P3743 kotori的设备

标签:return   line   就是   clu   www   cpp   print   ble   必须   

原文地址:https://www.cnblogs.com/Ax-Dea/p/12609798.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!