分块
题目大意
给定 \(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} \right \rfloor \times d) \le k\)
\(\displaystyle nd+\sum_{i=1}^{n} \left \lfloor \frac{a_i-1}{d} \right \rfloor \times d \le k + \sum_{i=1}^{n}a_i\)
\(\displaystyle d(n+\sum_{i=1}^{n} \left \lfloor \frac{a_i-1}{d} \right \rfloor )\le k + \sum_{i=1}^{n}a_i\)
右边为定值,左边 \(\displaystyle \left \lfloor \frac{a_i-1}{d} \right \rfloor\)有根号种取值,我们枚举它来计算符合条件的最大的 \(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;
}