题意很简单,就是叫你求,这个式子的最小值:
但不过有一些约束条件:

首先当时第一眼,直接均值不等式:

然后一会儿样例过了,然后WA了。

然后讲题解就看见一个拉格朗日乘子法。我虽然依稀会一点,但不过没有做过还有不等式约束的式子啊。。。。

然后看了一下拉格朗日乘子法和KTT没一个看懂,全是专业的数学用语,连例题都看不懂,还写了几个小时。哎太菜了。

后来看了看那些大佬的代码,发现看不懂。而且过了的都差不多。

我队友当时想了一种方法,就是理解上面的式子的图像意义。就是到ai/m这些点的距离的平方的最小值。然后对于为负数的点,相对应的pi取为零。

对为正数的ai/m用均值不等式。可以样例过不了。然后思考了很久,发现即使小于零也可以使用均值不等式。

如何判断呢?

首先,因为pi为大于零的数,ai为大于等于-m,小于等于m的数。假设前i个能取等号。在加上第i+1个能取等号。则必有这样的判断式:


这个可以通过经验和直觉得到。
如何证明呢,采用反证法:假设右边大的成立
则有这样的式子。


然后变一下形就成了这样了:

上面的式子表面pi+1是小于零的,于是与题意矛盾,故不成立,关于左边不大于的,这个和这个差不多,把公式变形就可以了。
#include "bits/stdc++.h"

using namespace std;
const double eps = 1e-8;
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define make_pair makp

int dcmp(double x) {
    if (fabs(x) < eps) return 0;
    return (x > 0) ? 1 : -1;
}

typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int N = 100000 + 10;
const int M = 2048 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 998244353;
ll n, m, a[N], sum[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0), cerr.tie(0);
    while (cin >> n >> m) {
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        sort(a + 1, a + n + 1, greater<>{});
        ll p, q, cnt = n;
        sum[0] = 0;
        for (int i = 1; i <= n; i++) {
            sum[i] = sum[i - 1] + a[i];
        }
        for (int i = 1; i < n; i++) {
            if (a[i + 1] * i < sum[i] - m) {
                cnt = i;
                break;
            }
        }
        q = cnt;
        p = (sum[cnt] - m) * (sum[cnt] - m);
        for (int i = cnt + 1; i <= n; i++) {
            p += a[i] * a[i] * q;
        }
        q *= m * m;
        ll d = __gcd(p, q);
        p /= d, q /= d;
        if (p == 0) cout << "0" << endl;
        else if (q == 1) cout << p << endl;
        else cout << p << "/" << q << endl;
    }
    return 0;
}