题目地址
题目大意:kotori有n个设备,每个设备使用速度为 每秒,一开始的电量为 ,一旦有一个设备电量为0即停止使用,有一个充电宝可以连续给一个设备每秒冲 的电量,求最多这套设备能用多久,如果用之不竭输出-1
数据范围:
读完题之后,我们会发现这道题珂以二分。二分主体不难写,我们来求最多使用时间,就设两个参数 和 ,指 区间, ,如果 参数是可以实现的,那么我们去尝试找更大的答案,即寻找区间 ,否则答案应该更小,即 (注意:这里精度较高,所以不能直接减1,不然直接 )
然后就是
函数了。
对于每种设备,分别有两种情况:
1.原来的电量可以持续
秒的时间,即
,不用通过充电器额外充电。
2.原来的电量不可以持续
秒的时间,即
,需要给予充电。
我们一步步算:
首先,第
个设备持续
秒的最少电量为
,如果
,就需要冲
的电量。充电宝每秒冲
的电量,即需要充
秒。
判断是否
可以成立的条件:
设第
个设备需要充电
秒,则如果
这种情况是可以的(因为充电时间没有超过
,即可以在充电时间不超过
的情况下让所有的设备电量都能维持
秒)
否则不成立。
的情况:
科学方法:在
的情况下,用之不竭(充电速度太快了
)
考场法:开始的区间设一个比较大的数
,从
开始查找,最后答案如果是是
就差不多是用之不竭了(
蒟蒻的垃圾码风
# 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;
}
(这题精度有点高啊,卡了我好几次
时间复杂度是
(?
感谢观看(点个关注吧