题意:
n根木棍中截取k根长度一样的木棍,多余的木棍舍去。
华华给月月准备礼物
思路:
先用最简单的方法从长度1开始一个一个枚举,直到达不到题目要求,这样的复杂度\thetaθ (n^2),显然会超时。我们就可以选区间的中点,如果不行答案一定比这个小,如果可以我们继续试试大一点可不可以,一步步缩小区间,这是二分的思路。
以前属于完全套一个模板,现在才了解了一点二分:
因为我是把答案存在l上,所以如果当前mid可行,那么l=mid,否则r=mid-1,直到l==r。
l左区间,r右区间,mid要取l+r+1,刘大佬和吴大佬说是为了防止除数为0,这个我没想到,还有一点是使mid偏大一点,避免死循环,如果是mid=l+r,当r-l=1时,如果答案是刚好是l–字母,那么就会出现一直执行l=l的情况,也就是mid不变。
注意:因为可能存在无解的情况,如果把解空间设为[1,最大的木棍长度],那么第一个测试点就会wa,所以我猜第一个测试点的答案是0。
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x;
}
void print(int x){
if(x>=10) print(x/10);
putchar(x%10+'0');
}
int a[200005],cnt,n,k;
bool check(int x) {
int ans=0;
for(int i=1;i<=n;++i) ans+=a[i]/x;
if(ans<k) return false;
return true;
}
int main() {
n=read(),k=read();
for(int i=1;i<=n;++i) {
a[i]=read();
if(a[i]>cnt) cnt=a[i];
}
int l=0,r=cnt;
while(l<r) {
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
print(l),puts("");
}