题目大意:kotori有n个设备,每个设备使用速度为 a i a_i ai每秒,一开始的电量为 b i b_i bi,一旦有一个设备电量为0即停止使用,有一个充电宝可以连续给一个设备每秒冲 p p p的电量,求最多这套设备能用多久,如果用之不竭输出-1
数据范围:
1 ≤ n , p , a i , b i ≤ 1 e 5 1\le n,p,a_i,b_i\le1e5 1≤n,p,ai,bi≤1e5
读完题之后,我们会发现这道题珂以二分。二分主体不难写,我们来求最多使用时间,就设两个参数 l l l和 r r r,指 [ l , r ] [l,r] [l,r]区间, m i d = l + r 2 mid=\frac{l+r}{2} mid=2l+r,如果 m i d mid mid参数是可以实现的,那么我们去尝试找更大的答案,即寻找区间 [ m i d , r ] [mid,r] [mid,r],否则答案应该更小,即 [ l , m i d ] [l,mid] [l,mid](注意:这里精度较高,所以不能直接减1,不然直接 G G \color{red}GG GG)
然后就是 c h e c k check check函数了。
对于每种设备,分别有两种情况:
1.原来的电量可以持续 m i d mid mid秒的时间,即 b i a i ≥ m i d \frac{b_i}{a_i}\ge mid aibi≥mid ,不用通过充电器额外充电。
2.原来的电量不可以持续 m i d mid mid秒的时间,即 b i a i < m i d \frac{b_i}{a_i}
我们一步步算:
首先,第 i i i个设备持续 m i d mid mid秒的最少电量为 m i d ⋅ a i mid·a_i mid⋅ai,如果 b i < m i d ⋅ a i bi
判断是否 m i d mid mid可以成立的条件:
设第 i i i个设备需要充电 t i t_i ti秒,则如果 ∑ i = 1 n t i ≤ m i d \sum_{i=1}^nt_i \le mid i=1∑nti≤mid
这种情况是可以的(因为充电时间没有超过 m i d mid mid,即可以在充电时间不超过 m i d mid mid的情况下让所有的设备电量都能维持 m i d mid mid秒)
否则不成立。
− 1 -1 −1的情况:
科学方法:在 ∑ i = 1 n a i ≤ p \sum_{i=1}^na_i \le p i=1∑nai≤p
的情况下,用之不竭(充电速度太快了 Q w Q QwQ QwQ)
考场法:开始的区间设一个比较大的数 R R R,从 [ 0 , R ] [0,R] [0,R]开始查找,最后答案如果是是 R R R就差不多是用之不竭了(
蒟蒻的垃圾码风 c o d e \color{blue}code code
# include
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<
}
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} lgR(?
感谢观看(点个关注吧