洛谷 P3743 kotori的设备 题解

题目地址

题目大意:kotori有n个设备,每个设备使用速度为 a i a_i 每秒,一开始的电量为 b i b_i ,一旦有一个设备电量为0即停止使用,有一个充电宝可以连续给一个设备每秒冲 p p 的电量,求最多这套设备能用多久,如果用之不竭输出-1

数据范围:
1 n , p , a i , b i 1 e 5 1\le n,p,a_i,b_i\le1e5

读完题之后,我们会发现这道题珂以二分。二分主体不难写,我们来求最多使用时间,就设两个参数 l l r r ,指 [ l , r ] [l,r] 区间, m i d = l + r 2 mid=\frac{l+r}{2} ,如果 m i d mid 参数是可以实现的,那么我们去尝试找更大的答案,即寻找区间 [ m i d , r ] [mid,r] ,否则答案应该更小,即 [ l , m i d ] [l,mid] (注意:这里精度较高,所以不能直接减1,不然直接 G G \color{red}GG

然后就是 c h e c k check 函数了。
对于每种设备,分别有两种情况:
1.原来的电量可以持续 m i d mid 秒的时间,即 b i a i m i d \frac{b_i}{a_i}\ge mid ,不用通过充电器额外充电。
2.原来的电量不可以持续 m i d mid 秒的时间,即 b i a i < m i d \frac{b_i}{a_i}<mid ,需要给予充电。
我们一步步算:
首先,第 i i 个设备持续 m i d mid 秒的最少电量为 m i d a i mid·a_i ,如果 b i < m i d a i bi<mid·a_i ,就需要冲 m i d a i b i mid·a_i-b_i 的电量。充电宝每秒冲 p p 的电量,即需要充 m i d a i b i p \frac{mid·a_i-b_i}{p} 秒。
判断是否 m i d mid 可以成立的条件:
设第 i i 个设备需要充电 t i t_i 秒,则如果 i = 1 n t i m i d \sum_{i=1}^nt_i \le mid
这种情况是可以的(因为充电时间没有超过 m i d mid ,即可以在充电时间不超过 m i d mid 的情况下让所有的设备电量都能维持 m i d mid 秒)

否则不成立。

1 -1 的情况:
科学方法:在 i = 1 n a i p \sum_{i=1}^na_i \le p
的情况下,用之不竭(充电速度太快了 Q w Q QwQ

考场法:开始的区间设一个比较大的数 R R ,从 [ 0 , R ] [0,R] 开始查找,最后答案如果是是 R R 差不多是用之不竭了(

蒟蒻的垃圾码风 c o d e \color{blue}code

# include <bits/stdc++.h>
using namespace std;
#define eps 0.000001
int n,p;
double a[100010],b[100010];
long double ans;
const double RR=1e10*1.0;
bool check(double mid) 
{
	double tot=0.000;
	for(int i=1;i<=n;i++) 
	{
		if(double(b[i])/double(a[i])>=mid) continue;
		else
		{
			double times=double(mid)-double(b[i])/double(a[i]);
			double energy=double(times)*double(a[i]);
			double f=double(energy)/double(p);
			tot=double(tot)+double(f);
		//	cout<<i<<" "<<times<<" "<<energy<<" "<<f<<" "<<tot<<endl;
		}
		if(tot>mid) return 0; 
	}
	if(tot<=mid) return 1;
	else return 0;
}
inline void js(double l,double r)
{
	if(r-l<=eps) return;
	double mid=double(l)+double(r);
	mid=double(mid)/2.0;
	if(check(mid)) 
	{
		ans=mid;
		js(mid,r);
	}
	else js(l,mid);
	return ;
}
int main(void) 
{
	scanf("%d%d",&n,&p) ;
	for(int i=1;i<=n;i++) 
	{
		cin >> a[i] >> b[i];
	}
	js(0,RR);
	if(RR-ans<=eps) cout<<-1;
	else cout<<fixed<<setprecision(400)<<ans<<endl;
	return 0;
}

(这题精度有点高啊,卡了我好几次
时间复杂度是 lg R \lg{R} (?
感谢观看(点个关注吧

发布了18 篇原创文章 · 获赞 2 · 访问量 3439

猜你喜欢

转载自blog.csdn.net/woshidalaocxy/article/details/104124351