笔试题1
题目描述: 有N根绳子,第i根绳子长度为L1,现在需要M根等长的绳子,你可以对N根绳子进行裁剪(不能拼接),请你帮忙计算出这M根绳子的最长的长度是多少?
如果最长的绳子足够长,那么就可以满足M根等长的绳子,所以二分搜索加贪心验证,二分绳子长度加判断是否满足。
二分长度,简单算下N*log(L)应该是可以过,所以二分最大长度,朴素的check是否满足就可以了
思路:能否等分出m个长度为L的绳子,在l ∈ [0, L] 上是个不减问题,即如果某个满足此条件的最大位置为l,则大于l的无法等分,小于l的可以等分
因此,二分满足题意的L,找到最大位置判断即可,复杂度已经算过是OK的,注意停止条件和输出位数有关;以及边界问题(r减 l不增,因为k是满足的)
#include<cstdio> #include<vector> #include<cmath> #include<algorithm> using namespace std; int n, m, x; vector<double> a; inline bool check(double l){ int count = 0; for(int i = n - 1; i >= 0 && a[i] >= l; --i){ count += floor(a[i] / l); } return count >= m; } inline double solve(int m){ double l = 0.f, r = a[n-1] + 1.f; while( r - l > 1e-3){ double k = (l + r) / 2; if (check(k)) l = k; else r = k - 0.001; } return l; } int main(){ scanf("%d%d", &n, &m); for(int i = 0; i < n; ++i){ scanf("%d", &x); a.push_back((double)x); } sort(a.begin(), a.end()); printf("%.2lf", solve(m)); return 0; }