P3743 kotori的设备

42 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情

kotori的设备

题目背景

kotori 有 nn 个可同时使用的设备。

题目描述

ii 个设备每秒消耗 aia_i 个单位能量。能量的使用是连续的,也就是说能量不是某时刻突然消耗的,而是匀速消耗。也就是说,对于任意实数,在 kk 秒内消耗的能量均为 k×aik\times a_i 单位。在开始的时候第 ii 个设备里存储着 bib_i 个单位能量。

同时 kotori 又有一个可以给任意一个设备充电的充电宝,每秒可以给接通的设备充能 pp 个单位,充能也是连续的,不再赘述。你可以在任意时间给任意一个设备充能,从一个设备切换到另一个设备的时间忽略不计。

kotori 想把这些设备一起使用,直到其中有设备能量降为 00。所以 kotori 想知道,在充电器的作用下,她最多能将这些设备一起使用多久。

输入格式

第一行给出两个整数 n,pn,p

接下来 nn 行,每行表示一个设备,给出两个整数,分别是这个设备的 aia_ibib_i

输出格式

如果 kotori 可以无限使用这些设备,输出 1-1

否则输出 kotori 在其中一个设备能量降为 00 之前最多能使用多久。

设你的答案为 aa,标准答案为 bb,只有当 a,ba,b 满足 abmax(1,b)104\dfrac{|a-b|}{\max(1,b)} \leq 10^{-4} 的时候,你能得到本测试点的满分。

样例 #1

样例输入 #1

2 1
2 2
2 1000

样例输出 #1

2.0000000000

样例 #2

样例输入 #2

1 100
1 1

样例输出 #2

-1

样例 #3

样例输入 #3

3 5
4 3
5 2
6 1

样例输出 #3

0.5000000000

提示

对于 100%100\% 的数据,1n1000001\leq n\leq 1000001p1000001\leq p\leq 1000001ai,bi1000001\leq a_i,b_i\leq100000

思路

很经典的二分答案,在验证一个使用时间的时候,如果当前设备已经有的能量大于使用需要的能量,那么就忽略该设备。否则那么就用充电器充电,设备已有的能量等于使用时间需要的能量,并记录需要的能量,最后比较需要的能量总和和充电器最多提供的能量。qaq,还是一个很基础的题目

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string> 
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack> 
#include <cmath>
#include <iomanip>
#define ll long long
#define AC return
#define Please 0
#define lowbit(x) x&(-x) 
using namespace std;
const int N=1e5+10;
typedef pair<int,int>PII;
typedef unsigned long long ull; 
inline int read(){//快读 
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=x*10+ch-'0'; 
		ch=getchar();
	}
	AC x*f;
}
vector<ll>alls;
double a[N],b[N];
int n;
double p;
bool check(double x){
	double c[N],d[N];
	for(int i=1;i<=n;i++){
		c[i]=a[i];
		d[i]=b[i];
	} 
	double tot=0;
	for(int i=1;i<=n;i++){
		d[i]-=x*c[i];
		if(d[i]<=0){
			tot+=(-d[i])/p;
		}
	}
	return tot<=x;
}
int main(){
	cin>>n>>p;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i]; 
	}
	long double l=0.0,r=1e10;
	while(r-l>1e-8){
		long double mid=(l+r)/2;
		if(check(mid)) l=mid;
		else r=mid;
	}
	if(r>1e10/2) cout<<-1;
	else printf("%.10Lf",r);
	//cout<<ans<<endl;
	AC Please;
}

希望能帮助到大家(QAQQAQ)!