分块

题目大意

给定 \(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;
}