zoukankan      html  css  js  c++  java
  • Codeforces Round #409 C. Voltage Keepsake(二分+思维)

    题目链接:http://codeforces.com/contest/801/problem/C

    题意:给出一个充电器每秒钟充p个点,还有n个电器要同时使用a[i]表示第i个电器每秒钟用多少点,b[i]表示第i个

    原来存了都少电。充电器可以无缝切换这充电,但是只能给一个充(同一时间)。最后问你最长可用多久,如果可以

    无限时间的用的话,就输出-1。

    题解:首先确定一下什么时候输出-1也就是可以无限充电的情况,就是p大于所有a的总和就行。

    然后就是时间有限的情况。这里明确一个式子。

    need*t=a[i]*t-b[i],(need表示每秒需要的时间,t表示时间)然后for一下1~n

    need+=(a[i]-b[i]/t) 

    如果need<=p那么这个时间就是符合的。

    然后就是枚举时间,枚举时间可以用二分,不妨设l=0,r=1e10,mid=(l+r)/2。然后就是二分的次数,由于精度要求是

    1e-4所以二分50次左右就够了。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int M = 1e5 + 10;
    double a[M] , b[M];
    int main() {
        int n;
        double p;
        scanf("%d%lf" , &n , &p);
        double sum = 0;
        for(int i = 0 ; i < n ; i++) {
            scanf("%lf%lf" , &a[i] , &b[i]);
            sum += a[i];
        }
        if(sum <= p) {
            cout << -1 << endl;
        }
        else {
            double l = 0 , r = 1e10;
            double mid = (l + r) / 2;
            for(int j = 1 ; j <= 50 ; j++) {
                mid = (l + r) / 2;
                double need = 0;
                for(int i = 0 ; i < n ; i++) {
                    need += max(0.0 , 1.0 * a[i] - b[i] / mid);
                }
                if(need <= p) l = mid;
                else r = mid;
            }
            printf("%.10lf
    " , l);
        }
        return 0;
    }
    
  • 相关阅读:
    QDUOJ LC的课后辅导 单调递增栈
    蓝桥杯 时间问题
    区间sum 和为k的连续区间-前缀和
    康托展开-全排列的编码与解码
    康托展开-全排列应用
    背包之01背包、完全背包、多重背包详解
    HDU
    辗转相除求最大公约数与最小公倍数
    快速幂(反复平方法)
    HDU
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6722021.html
Copyright © 2011-2022 走看看