1 条题解

  • 0
    @ 2021-9-22 20:13:08

    P3743 kotori的设备

    Part 1 无限使用

    很简单,只要所有设备一秒内消耗的能量小于等于充电宝一秒内能提供的能量,就意味着能够一直充电。

    Part 2 主程序

    既然所有和的最大值是 101010^{10} 那么就把右边界定义为 101010^{10}

    然后,题目要求的精度是 10410^{-4} ,所以当 rrll 相差小于等于 10410^{-4} 时结束 while 循环。

    这样看似范围很大,但是二分的时间复杂度是 O(logn)O(\log n) ,即使是大数据也就几十而已。

    Part 3 check 函数

    设待验证的时间为 xx 则充电宝最多可以提供 xpx*p 的能量。设 tt 表示在时间 xx 内所需充电宝能量,则如果一个设备在 xx 秒内消耗的能量小于原来储存的能量,就不需要使用充电宝。

    反之,如果要使用充电宝,那么充电宝消耗的能量就是这个设备在 xx 秒内消耗的能量减去原储存能量。用 tt 做一个累加即可。

    最后如果 tt 小于等于 pp ,就意味着这个时间是合法的。

    AC code :

    #include<bits/stdc++.h>
    using namespace std;
    struct aksres
    {
    	double x,y;
    }a[233333];
    int n;
    double p,sum,l,r,mid;
    int check(double x)
    {
    	double s=x*p,t=0;
    	for(int i=1;i<=n;i++) t+=max(0,x*a[i].x-a[i].y);
    	return t<=s;
    }
    int main()
    {
    	cin>>n>>p;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lf%lf",&a[i].x,&a[i].y);
    		sum+=a[i].x;
    	}
    	if(sum<=p) {cout<<"-1";return 0;}
    	l=0.0;r=1e10;
    	while(r-l>0.0001)
    	{
    		mid=(l+r)/2.0;
    		if(check(mid)) l=mid;
    		else r=mid;
    	}
    	printf("%.6lf",l);
    	return 0;
    }
    
    • 1

    信息

    ID
    2676
    时间
    1000ms
    内存
    125MiB
    难度
    3
    标签
    递交数
    11
    已通过
    2
    上传者