- 二分答案,求出烘干的最小次数mid
- check(mid)怎么写呢?
- 对于a[i],如果a[i]<=mid,可以自己晾干不用管
- a[i]>mid,需要烘***烘干
- 设烘干次数为cnt,因为不能烘干到0,所以
- 只需要烘干到<=自然可以晾干即可
- 烘干用了cnt分钟,剩余自然晾干的时间为mid-cnt
- 列出方程a[i]-cnt*k<=mid-cnt
- 移项得到cnt>=(a[i]-mid)/(k-1)
- (a[i]-mid)/(k-1)需要向上取整,
- a/b向上取整公式(a+b-1)/b
- cnt=(a[i]-mid+k-1-1)/(k-1)
- 把每个a[i]的贡献累加
- cnt+=(a[i]-mid+k-1-1)/(k-1)
- 剪枝cnt>mid不合法提前返回false
- 最后cnt<=mid就是合法答案
时间复杂度是O(nlogmx)最大就是30*1e5的操作量
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int a[N];
int n, k;
bool check(int mid){
long long cnt = 0; //烘干次数
for(int i=1;i<=n;i++){
if(a[i] > mid)//无法自然烘干
cnt += (a[i] - mid + k - 1 - 1) / (k - 1);
if(cnt > mid) return false; //次数超了不合法
}
return cnt <= mid;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
//读取数据,基本功
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
cin>>k;
//答案的上界mx
int mx=0;for(int i=1;i<=n;i++)mx=max(mx,a[i]);
//除数不为0,所以k=1需要特判
if(k==1){cout<<mx<<'\n';return 0;}
//二分答案,答案最小值模版
int l=1,r=mx,ans=0;
while(l <= r){
int mid = l + (r-l)/2;
if(check(mid))
ans = mid,r = mid - 1;
else
l = mid + 1;
}
cout<<ans<<'\n';
return 0;
}