这道题的数据范围其实已经是很大的提示了;
读懂题后,简单的推一下,就能得到一个不等式:
这个不等式吧里面的求和可以直接暴力累加,因为n只有100。
那么最重要的是如何快速枚举n呢??
这里就要用到数论分块的知识了:
给一个定值x,和一个变量a(1<a<x)那么x除以a向下取整所得的取值最多只有二倍的根号x种取值;
现在,有了这个理论的支撑,我们就能很轻松的做出这道题了:
k+sum进行关于d的整数分块,枚举每一个块的右端点,若满足该不等式,则更新答案,一直枚举到上界max+k停止;
那么就有一个问题出现了:为什么只用枚举每一个块的右端点呢?
其实很简单:ai/d是随着d的增大而不增加的,就是说近似的单调递减。所以如果右端点不满足,那么同一个块里的其他取值肯定也不满足。
细节看代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n,k,maxx=0,sum=0,ans;
LL a[453453];
LL ceil(LL x,LL y)
{
if(x%y==0) return x/y;
else return x/y+1;
}
int main()
{
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]),maxx=max(maxx,a[i]),sum+=a[i];
maxx+=k;sum+=k;
for(LL d=1;;d=sum/(sum/(d+1)))
{
LL sigma=0;
for(int i=1;i<=n;++i)
sigma+=ceil(a[i],d);
sigma=sigma*d;
if(sigma<=sum) ans=d;
if (d>maxx||d+1>sum) break ;
}
printf("%lld",ans);
return 0;
}