分块
题目大意
给定 (n) 个数 (a_1) ~ (a_n) ,求最大的 (d) , 满足 (displaystyle sum_{i=1}^{n}d-((a_i-1)\%d + 1) le k)
首先我们看到取模很难化简式子,考虑用除法代替。
(displaystyle nd-sum_{i=1}^{n}(a_i- left lfloor frac{a_i-1}{d} ight floor imes d) le k)
(displaystyle nd+sum_{i=1}^{n} left lfloor frac{a_i-1}{d} ight floor imes d le k + sum_{i=1}^{n}a_i)
(displaystyle d(n+sum_{i=1}^{n} left lfloor frac{a_i-1}{d} ight floor )le k + sum_{i=1}^{n}a_i)
右边为定值,左边 (displaystyle left lfloor frac{a_i-1}{d} ight floor)有根号种取值,我们枚举它来计算符合条件的最大的 (d) 即可。
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
LL n, k, mx, s, tmp, ans;
LL a[105];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++i)scanf("%lld", &a[i]), k += a[i], mx = max(mx, a[i] - 1);
for (LL l = 1, r; l <= mx; l = r + 1)
{
r = 1e18; s = 0;
for (int i = 1; i <= n; ++i)
if (a[i] - 1 >= l)
{
s += (a[i] - 1) / l;
r = min(r, (a[i] - 1) / ((a[i] - 1) / l));
}
tmp = k / (s + n);
if (l <= tmp)ans = max(ans, min(tmp, r));
}
if (mx < k / n)ans = max(ans, k / n);
cout << ans;
return 0;
}