已知  ,, ,求 的最小值

------------------------------------------------

1、首先将常数m从式子中提出来

2、 同时乘上一个 m 

3、我们知道对于平方和来说,为了使和更小,我们尽量将最大的数字最小化,才能使和最小

比如说 ,我们将3减少一,等到的平方和是 ,将6减少一,得到的平方和是 ,显然将最大数字最小化是最好的选择。

4、但由于 ,所以上一步我们只能优化 为正的项,使他们的最大值尽量小,考虑一种情况,所有大于0的  都已经减少到0了,但此时,就是说还有一部分  没有放入式子中,由于此时所有的  都是非正的了,所以我们可以考虑将括号里面改变一下符号,就变成了  ,为了使这个值尽量小,我们希望尽量少的出现较大的值,所以我们考虑使他的最小值尽量大。也就是让  尽量平均。

5、所以我们发现对于  来说,无论他是正数还是负数,为了使原式尽量小,我们希望让  的最大值尽量小,

6、每次先计算出将目前遍历到的所有元素变为当前元素所花费的代价,如果小于等于m,更新,否则,记一个标记,在这个标记前的都可以更新到同一个值,后面的元素就暴力算。

Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[10005];
ll gcd(ll a, ll b)
{
	return b == 0 ? a : gcd(b, a % b);
}
int main()
{
	int n, m, t;
	while (scanf("%d%d", &n, &m) > 0)
	{
		int temp = m;
		ll ans = 0;
		for (int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		sort(a + 1, a + 1 + n, greater<int>());
		int index = n;
		for (int i = 1; i <= n; i++)
		{
			int cost = (i - 1) * (a[i - 1] - a[i]);
			if (cost <= m)
				m -= cost;
			else
			{
				index = i - 1;
				break;
			}
		}
		ans = (index * a[index] - m) * (index * a[index] - m);
		for (int i = index + 1; i <= n; i++)
		{
			ans += a[i] * a[i] * index;
		}
		ll ans2 = temp * temp * index;
		int g = gcd(ans, ans2);
		ans /= g, ans2 /= g;
		if (ans2 == 1)
			printf("%lld\n", ans);
		else
		printf("%lld/%lld\n", ans, ans2);
	}
}