[USACO17JAN]Building a Tall Barn建谷仓
神奇的二分
题解:
Luogu题解。
令 ti 表示 第i层多一头牛的改变量
ti=a[i]/ci∗(ci+1)
最终状态中 ti 一定是很接近的,否则可以从j拿一头牛到i去,使得结果更优
所以我们就二分 ti
ti=a[i]/ci∗(ci+1) —> ci2+ci−ai/ti=0
反解出ci,然后对ci求和,如果不到k-n则可以缩小上界,否则提高下界。
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-9;
const int N = 100005;
int n; double a[N];
long long m;
bool check(double t){
long long sum=0; double c;
for(int i=1;i<=n;i++){
c=(sqrt(1+4*a[i]/t)-1)/2;
sum+=ceil(c);
if(sum>m) return false;
}
return true;
}
int main(){
freopen("a.in","r",stdin);
scanf("%d%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lf",a+i);
double l=eps,r=12,mid;
for(int i=1;i<=50;i++){
mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
double t=mid,c,ans=0.0; long long sum=0;
for(int i=1;i<=n;i++){
c=(sqrt(1+4*a[i]/t)-1)/2;
sum+=ceil(c);
ans+=a[i]/ceil(c);
}
// printf("%.5f\n",t);
// printf("%.5f\n",ans);
printf("%.0f\n",ans-(m-sum)*t);
}