数学 砍树

这里写图片描述
Σ (向上取整(a[i]/d)*d-a[i])<=k
Σ(向上取整(a[i]/d))<=k+Σa[i](总称为C)
Σ向上取整(a[i]/d)<=向下取整(C/d);
f(d)=Σ向上取整(a[i]/d),g(d)=向下取整(C/d)
易知两个函数都是单调不上升的。具体来说都是分段的,那么对于g(d)的同一段上,段尾的d值一定优于段首值(f(d)也单调下降)。
那么枚举每一个段尾的d值,暴力求f(d),更新答案即可。
PS:设段首为i,段尾=C/(C/i);神奇。。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
int n;
ll k,a[105],ans;
inline int read()
{
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}
    return sum*f;
}
int main()
{
    n=read();scanf("%lld",&k);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),k+=a[i];
    ll i=1,j,t;
    while(1)
    {
        t=k/i;if(t==0)break;
        j=k/t;ll sum=0;
        for(int l=1;l<=n;l++)
        {
            ll h=a[l]/j;
            if(h*j<a[l])h++;
            sum+=h;if(sum>t)break;
        }
        if(sum<=t)ans=j;
        i=j+1;
    }   
    cout<<ans;
}
原文地址:https://www.cnblogs.com/QTY2001/p/7632678.html