洛谷P2440 木材加工

木材加工

题目背景

要保护环境

题目描述

木材厂有 nn 根原木,现在想把这些木头切割成 kk 段长度ll 的小段木头(木头有可能有剩余)。

当然,我们希望得到的小段木头越长越好,请求出 ll 的最大值。

木头长度的单位是 cm\text{cm},原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为 11112121,要求切割成等长的 66 段,很明显能切割出来的小段木头长度最长为 55

输入格式

第一行是两个正整数 n,kn,k,分别表示原木的数量,需要得到的小段的数量。

接下来 nn 行,每行一个正整数 LiL_i,表示一根原木的长度。

输出格式

仅一行,即 ll 的最大值。

如果连 1cm\text{1cm} 长的小段都切不出来,输出 0

样例 #1

样例输入 #1

3 7
232
124
456

样例输出 #1

114

提示

数据规模与约定

对于 100%100\% 的数据,有 1n1051\le n\le 10^51k1081\le k\le 10^81Li108(i[1,n])1\le L_i\le 10^8(i\in[1,n])

P2440 木材加工 - 洛谷

思路

P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷类似,容易想到暴力枚举,但考虑数据范围,暴力枚举会超时,应使用时间复杂度更优的算法。因答案所在区间满足单调性,容易想到二分答案,用二分答案即可解。这个基本上就改那道题的check函数就行了

check函数,这里写匿名函数,不懂匿名函数的自行补全成 C 函数就好,就是标头不一样

[&](auto &&mid) {        //bool check(int mid) {
    i64 h = 0;
    for (auto &&i : arr)
        if(mid != 0)
            h += i / mid;
        else
            isNotZero = false;
    return h >= m;
}

这里用到C++20的ranges库的二分答案函数,不会的自己搓二分模板也行

C++20代码

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    i64 n, m, isNotZero = (cin >> n >> m, true);
    vector arr(n, 0ll);
    for (auto &&i : arr)
        cin >> i;
    cout << *ranges::partition_point(
        views::iota(0ll, *max_element(arr.begin(), arr.end())),
        [&](auto &&mid) {
            i64 h = 0;
            for (auto &&i : arr)
                if(mid != 0)
                    h += i / mid;
                else
                    isNotZero = false;
            return h >= m;
        }) - isNotZero;
    return 0;
}

洛谷P2440 木材加工
https://winterl-blog.netlify.app/2023/12/24/洛谷P2440 木材加工/
作者
winterl
发布于
2023年12月24日
许可协议