前言
九月应该是人生中最后一次CSP了,已经7个多月没碰编程的我显然已经有些力不从心,达到一年前的水平更是不可能。只能写点简单的题目来提升一下。祝我CSP RP++。
题意
小鸟有 nnn 个可同时使用的设备。
第 iii 个设备每秒消耗 aia_iai 个单位能量。能量的使用是连续的,也就是说能量不是某时刻突然消耗的,而是匀速消耗。也就是说,对于任意实数,在 kkk 秒内消耗的能量均为 k×aik\times a_ik×ai 单位。在开始的时候第 iii 个设备里存储着 bib_ibi 个单位能量。
同时小鸟又有一个可以给任意一个设备充电的充电宝,每秒可以给接通的设备充能 ppp 个单位,充能也是连续的,不再赘述。你可以在任意时间给任意一个设备充能,从一个设备切换到另一个设备的时间忽略不计。
小鸟想把这些设备一起使用,直到其中有设备能量降为 000。所以小鸟想知道,在充电器的作用下,她最多能将这些设备一起使用多久。
说明/提示
对于 100%100\%100% 的数据,1≤n≤1000001\leq n\leq 1000001≤n≤100000,1≤p≤1000001\leq p\leq 1000001≤p≤100000,1≤ai,bi≤1000001\leq a_i,b_i\leq1000001≤ai,bi≤100000。
输入格式
第一行给出两个整数 n,pn,pn,p。
接下来 nnn 行,每行表示一个设备,给出两个整数,分别是这个设备的 aia_iai 和 bib_ibi。
输出格式
如果小鸟可以无限使用这些设备,输出 −1-1−1。
否则输出小鸟在其中一个设备能量降为 000 之前最多能使用多久。
设你的答案为 aaa,标准答案为 bbb,只有当 a,ba,ba,b 满足
∣a−b∣max(1,b)≤10−4\dfrac{|a-b|}{\max(1,b)} \leq 10^{-4}max(1,b)∣a−b∣≤10−4 的时候,你能得到本测试点的满分。
思路
一眼二分答案板题,根据答案进行二分(废话)。
首先判断无限使用情况。容易发现单位时间内输入电能大于消耗电能时,可以无限使用,即:
Σi=1nai≤p\Sigma^{n}_{i=1}{a_i} \leq pΣi=1nai≤p
时输出 -1
。
对于二分部分,可以让右端点取在 Σi=1naiΣi=1nbi−p\dfrac{\Sigma^{n}_{i=1}{a_i}}{\Sigma^{n}_{i=1}{b_i} - p}Σi=1nbi−pΣi=1nai 的理论最多使用时间,左端点取 000 即可。二分时比较 nnn 台设备运行 ttt 个单位时间的时候需要额外输入总电能和该时间段可以输入的总电能即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
double p,a[100005],b[100005],tot = 0;
double l = 0,r,mid;
bool check(double t) {
double elec = t * p;//时间段输入总电能
for(int i = 1;i <= n;i++) {
if(b[i] >= a[i] * t) continue;
double need = a[i] * t - b[i];
if(elec >= need) elec -= need;//扣去第 i 个设备消耗电能
else return false;
}
return true;
}
signed main() {
scanf("%lld %lf",&n,&p);
for(int i = 1;i <= n;i++) {
scanf("%lf %lf",&a[i],&b[i]);
tot += a[i];
r += b[i];
}
if(tot <= p) {
printf("-1\n");
return 0;
}
r /= (tot - p);
while(l < r - 0.000001) { //注意区间大小,过小会TLE,过大会WA
mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
printf("%lf\n",l);
return 0;
}