题意:
n根木棍中截取k根长度一样的木棍,多余的木棍舍去。
思路:
先用最简单的方法从长度1开始一个一个枚举,直到达不到题目要求,这样的复杂度 (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。
Code:
#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(""); }