AcWing寒假每日一题——Day6剪绳子

剪绳子

N N N根绳子,第i根绳子长度为 L i Li Li,现在需要 M M M根等长的绳子,你可以对 N N N根绳子进行任意裁剪(不能拼接),请你帮忙计算出这 M M M根绳子最长的长度是多少。

输入格式
第一行包含 2 2 2个正整数 N 、 M N、M NM,表示原始绳子的数量和需求绳子的数量。

第二行包含 N N N个整数,其中第 i i i 个整数 L i Li Li表示第 i i i 根绳子的长度。

输出格式
输出一个数字,表示裁剪后最长的长度,保留两位小数。

数据范围
1 ≤ N , M ≤ 100000 , 1≤N,M≤100000, 1N,M100000,
0 < L i < 1 0 9 00<Li<109
输入样例:

3 3 3 4 4 4
3 3 3 5 5 5 4 4 4

输出样例:

2.50 2.50 2.50

样例解释
第一根和第三根分别裁剪出一根 2.50 2.50 2.50长度的绳子,第二根剪成 2 2 2 2.50 2.50 2.50长度的绳子,刚好 4 4 4根。

分析:
这是一道二分题,可以直接二分搜索绳子的长度,这是一个浮点数二分模板。为什么能想到二分搜索呢?如果我们找到一个长度 l e n len len,使得 m = ∑ i = 0 n ⌊ a [ i ] l e n ⌋ m=\sum_{i=0}^{n} \left \lfloor \frac{a[i]}{len} \right \rfloor m=i=0nlena[i],那么小于 l e n len len的长度都满足上面的式子,符合二分的性质。
接下来就直接套浮点数二分的模板了:

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],m,n;
bool check(double len){
     
    int res=0,i;
    for(i=0;i<n;i++){
     
        res+=a[i]/len;
    }
    if(res>=m) return true;
    else return false;
}
int main(){
     
    int i;
    cin>>n>>m;
    for(i=0;i<n;i++){
     
        cin>>a[i];
    }
    double l=0,r=1e9;
    while(r-l>1e-3){
     
        double mid=l+(r-l)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%.2lf\n",l);
}

你可能感兴趣的:(算法)