刷题笔记:Luogu P3743

题目传送门

Solution

最多能将这些设备一起使用多久,显然答案满足单调性(如果\(x<y\)而不能使用\(x\)时间则一定不能使用\(y\)时间)

通俗一点,就是前边的时间不满足则后边一定不满足,也就是局部答案舍弃性,考虑二分时间

至于check怎么写呢?

奶牛晒衣服有异曲同工之妙,若设二分出来的时间为\(t\),如果每台设备需要充电宝才能至少支持\(t\)秒,将需要充电宝支持的时间累计为\(sum\),最后判断\(sum\leq t\)即可

由于实数二分,我们不能直接按照题意模拟(不能使用枚举到\(t\)的做法,因为\(t\)是实数)

实数二分还需要控制一下精度,大概是这样的:

实数二分的时候:如果误差小于四位小数,eps就等于1e-6,如果误差小于五位小数,eps就等于1e-7,如果误差小于六位小数,eps就等于1e-8。就是比误差多两位就可以。
(eps指while(r-l>eps)

具体做法见代码吧 卡精度真的恶心人啊

CODE

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define INF 1e10 
#define N 1000010
#define  MINN 1e-6 //开大一点也没关系
using namespace std;
int n,p;
int a[N],b[N];
struct Node
{
    double a,b;
}cpy[N];
void copy()
{
    for(int i=1;i<=n;i++) 
    {
        cpy[i].a = a[i];
        cpy[i].b = b[i];
    }
}
bool cmp(Node a,Node b)
{
    return (a.b-a.a) < (b.b-b.a);
}
bool check(double x)
{
    copy(); //闲的,显然没必要,但是懒得删了()
    double power = 0;
    for(int i=1;i<=n;i++)
    {
        if(cpy[i].a*x > cpy[i].b) power += cpy[i].a*x*1.0-cpy[i].b; 
    }
    return power <= p*x;
}
int main()
{
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    double l = 0,r = INF;
    while(r - l > MINN)
    {
        double mid = (l+r)/2;
        if(check(mid)) l = mid;
        else r = mid -MINN; //这里也需要注意一下精度
    }
   if(r == INF) printf("-1\n");
   else printf("%.10lf\n",r);
    return 0;
}
posted @   SXqwq  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示