我们考虑朴素算法,假设Max为给出木条的最大长度,直接枚举长度 0~Max,找到符合情况的最大值即可,由于最大长度可以为1e9,复杂度最差为O(1e9n)显然不行,观察发现,如果对于裁剪出长度为x的木条最多能凑出sum根,那么裁剪x+1长度的木条,肯定不会得到sum+1根,很明显,具有单调性,我们就能考虑二分。就像猜数字一个,每次猜一个数,判断能不能,如果符合,就可以往大的猜,如果不可以,就缩小。由于木条最大长度是1e9,所以二分复杂度为O(log1e9),对于判断,只需要遍历一遍全部木条即可,复杂度为O(n),总复杂度为O(nlog1e9)。
#include <cstring> #include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <map> #include<time.h> using namespace std; typedef long long ll; const int maxn=2e5+10; int n,m,A[maxn]; bool check(ll m1) { if (m1==0) return true; ll cnt=0; for (int i=1; i<=n; i++) { cnt+=A[i]/m1; } return cnt>=m; } int main(){ scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) { scanf("%d",&A[i]); } ll l=0,r=1e9; ll ans=0; while (l<=r) { ll m1=l+(r-l+1)/2; if (check(m1)) { l=m1+1; ans=m1; } else r=m1-1; } printf("%lld\n",ans); return 0; }