codeforces C. Voltage Keepsake (浮点数二分坑点控制精度可解决)

题意:
给你n个装置,每个装置每分钟耗电p ,本身储存电c。
然后你有一个充电器,(随时充,转移不耗时,想怎么换着充都行)。
问你让所有装置都能保持工作的最大时间是多少。

以前模板都是用 1e-9 但是这里其实只需要到1e-5(虽然这能水过,但是这不是重点)。
。所以减少精度或者限定次数都可以。他们都是迭代 150到300次这样。。。注意这里要开longlong 重点。为什么要限定次数,因为浮点数的折半查找不安全, 它是用 r-l>0的这样一种模式,所以它会卡在某个点。实际上 递归次数到300这样精度已经很准确。这个时间复杂度 为 递归的次数n次数 也就是如果递归次数为1000 1e5 那么就是1e8
那就已经快超时了 达到了 500ms *4 就gg了 就是2s了

所以浮点数这样的超时的。。。一般加个(右边界-左边界) *精度就好
一般300肯定够了 也不会超时

#include 
using namespace std;
typedef long long ll;
int n,a[101010],b[101001];
int p;
int check(double x)
{
    double res=0;
    for(int i=0;iif(a[i]*1.0*x*10>(b[i]*1.0*10))
        {
            res+=(a[i]*1.0*x-(b[i]*1.0))/p;
        }
    }
    if(res<=x){
        return 1;
    }
    else return 0;
}
int main()
{
    scanf("%d%d",&n,&p);
    ll s=0;
    for(int i=0;iscanf("%d%d",&a[i],&b[i]);
        s+=a[i];
    }

        if(p>=s)
        {
            printf("-1\n");
        return 0;
        }

    double l=0.0,r=1e18;
    long long cnt=0;
    while(r-l>1e-9)
    {
        cnt++;
        double mid=(l+r)/2;
        if(check(mid))
            l=mid;
        else
            r=mid;
        if(cnt>300) break;
    }
    printf("%.5lf\n",l );
}

或者控制精度即可

#include 
using namespace std;
typedef long long ll;
int n,a[101010],b[101001];
int p;
int check(double x)
{
    double res=0;
    for(int i=0;iif(a[i]*1.0*x*10>(b[i]*1.0*10))
        {
            res+=(a[i]*1.0*x-(b[i]*1.0))/p;
        }
    }
    if(res<=x){
        return 1;
    }
    else return 0;
}
int main()
{
    scanf("%d%d",&n,&p);
    ll s=0;
    for(int i=0;iscanf("%d%d",&a[i],&b[i]);
        s+=a[i];
    }

        if(p>=s)
        {
            printf("-1\n");
        return 0;
        }

    double l=0.0,r=1e18;
    long long cnt=0;
    while(r-l>=1e-4)
    {
        cnt++;
        double mid=(l+r)/2;
        if(check(mid))
            l=mid;
        else
            r=mid;
    }
    printf("%.5lf\n",l );
}

你可能感兴趣的:(codeforces,二分)