题意: 给出若干个木棍长度,你可以对每个木棍进行切割。
比如 有5个木棍,长度分别是4 4 4 5 3
你可以一次切长度为2的,那么4能切2刀,5能切2刀,3只能切一刀。总数加起来ans=2+2+2+2+1=9
题目问的就是一次切w刀,能使的ans>K.(K由题目给出),算出max(w)
数据范围:
n=2e5 木棍最大长度1e9
很显然这是一道二分的题目,二分一次切W刀,其实我们可以发现,最大切的次数应该是最大木棍长度,因为大于最大木棍长度没法切了嘛。
所以我们最大二分的区间是[1-1e9]
由于题目要最大值,我们只需要当ans>K的时候,记录最大值即可,注意二分的右边界需要+1,不然这组数据过不去
5 1
4 4 4 5 3
复杂度是n*logn
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <map> #include <queue> #include <deque> #include <set> #include <stack> #include <cctype> #include <cmath> #include <cassert> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const ll mod=1000000007; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} const int N=2e5+100; ll a[N]; ll n,L; int main() { scanf("%lld%lld",&n,&L); ll maxx=-1e18; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); maxx=max(maxx,a[i]); } // if(L==1) // { // printf("%lld\n",maxx); // return 0; // } ll l=1; ll r=maxx+1; ll res=-1e18; while(l<r) { ll mid=(l+r)/2ll; ll ans=0; for(int i=1;i<=n;i++) { ans+=a[i]/mid; } //printf("mid:%lld ans:%lld\n",mid,ans); if(ans<L) { r=mid; } else { res=max(res,mid); l=mid+1; } } if(res==-1e18) { printf("0\n"); } else { printf("%lld\n",res); } return 0; }