题意很简单,就是叫你求,这个式子的最小值:
但不过有一些约束条件:
首先当时第一眼,直接均值不等式:
然后一会儿样例过了,然后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; }