【2019牛客暑期多校训练营第一场 C题 Euclidean Distance】【拉格朗日乘子法】

题目链接:
https://ac.nowcoder.com/acm/contest/881/C
题意:
现给你一个n维空间中的点 a = ( a 1 , a 2 , ⋅ ⋅ ⋅ , a n ) a = (a_1, a_2,···, a_n) a=(a1,a2,,an),保证 a i a_i ai为整数,现在求另外一个n维空间中的点 p p p,需要满足条件:
p 1 , p 2 , ⋅ ⋅ ⋅ , p n ∈ R p_1, p_2, ···, p_n ∈ R p1,p2,,pnR
p 1 , p 2 , ⋅ ⋅ ⋅ , p n ≥ 0 p_1, p_2, ···, p_n \geq 0 p1,p2,,pn0
∑ i = 1 n p i = 1 \displaystyle\sum_{i = 1}^{n}p_i = 1 i=1npi=1
④使得 ∑ i = 1 n ( a i m − p i ) 2 \displaystyle\sum_{i = 1}^{n}(\frac{a_i}{m} - p_i)^2 i=1n(maipi)2最小
最后输出这个式子的最小值
题解:
题目就是在满足一定约束条件下目标函数的最小值,如果没有那个不等式条件那就简单多了,用拉格朗日乘数法就解决了,但是这里多了一个条件②那样的不等式条件,所以用到了拉格朗日乘子法。
首先需要构造一个拉格朗日函数 L ( p 1 , p 2 , ⋅ ⋅ ⋅ , p n , λ ) = ∑ i = 1 n ( a i m − p i ) 2 + 2 λ ( ∑ i = 1 n p i − 1 ) L(p_1, p_2, ···, p_n, \lambda) = \displaystyle\sum_{i = 1}^{n}(\frac{a_i}{m} - p_i)^2 + 2\lambda(\displaystyle\sum_{i = 1}^{n}p_i - 1) L(p1,p2,,pn,λ)=i=1n(maipi)2+2λ(i=1npi1)
如果没有那个不等式条件,只需要对所有项求偏导等于0,即
L p 1 = 2 ( a 1 m − p 1 ) ( − 1 ) + 2 λ = 0 L_{p_1} = 2(\frac{a_1}{m} - p_1)(-1) + 2\lambda = 0 Lp1=2(ma1p1)(1)+2λ=0
L p 2 = 2 ( a 2 m − p 2 ) ( − 1 ) + 2 λ = 0 L_{p_2} = 2(\frac{a_2}{m} - p_2)(-1) + 2\lambda = 0 Lp2=2(ma2p2)(1)+2λ=0
⋅ ⋅ ⋅ ···
L p n = 2 ( a n m − p n ) ( − 1 ) + 2 λ = 0 L_{p_n} = 2(\frac{a_n}{m} - p_n)(-1) + 2\lambda = 0 Lpn=2(manpn)(1)+2λ=0
L λ = ∑ i = 1 n p i − 1 = 0 L_{\lambda} = \displaystyle\sum_{i = 1}^{n}p_i - 1 = 0 Lλ=i=1npi1=0
但是这里有 p 1 , p 2 , ⋅ ⋅ ⋅ , p n ≥ 0 p_1, p_2, ···, p_n \geq 0 p1,p2,,pn0,需要一项项带进去检验 p i ≥ 0 p_i \geq 0 pi0,如果不满足就舍弃即 p i = 0 p_i = 0 pi=0(取0是因为 p i ≥ 0 p_i \geq 0 pi0
先对数组 a a a从小到大排序
从上面的求偏导我们可以得到 p i = a i m − λ p_i = \frac{a_i}{m} - \lambda pi=maiλ,如果当前已检查过符合条件的 p i p_i pi的个数为 k k k
那么此时 L λ = ∑ i = 1 k p i − 1 = 0 L_{\lambda} = \displaystyle\sum_{i = 1}^{k}p_i - 1 = 0 Lλ=i=1kpi1=0 可以得到 λ = ∑ i = 1 k ( a i ) − m m k \lambda = \frac{\displaystyle\sum_{i = 1}^{k}(a_i) - m}{mk} λ=mki=1k(ai)m,带入 p k + 1 = a k + 1 m − λ p_{k+1} = \frac{a_{k+1}}{m} - \lambda pk+1=mak+1λ
得到 m k p k + 1 = k a k + 1 − ∑ i = 1 k a i + m ≥ 0 mkp_{k+1} = ka_{k+1} - \displaystyle\sum_{i = 1}^{k}a_i + m \geq 0 mkpk+1=kak+1i=1kai+m0,如果符合条件继续判断下一项,如果不行那就停止(因为先排过序,之后结果只会更小)

现在假设最后的项数为 k k k,则 p k + 1 , p k + 2 , ⋅ ⋅ ⋅ , p n p_{k+1}, p_{k+2}, ···, p_n pk+1,pk+2,,pn均为0
∑ i = 1 n ( a i m − p i ) 2 \displaystyle\sum_{i = 1}^{n}(\frac{a_i}{m} - p_i)^2 i=1n(maipi)2
= ∑ i = 1 k ( a i m − p i ) 2 + ∑ i = k + 1 n a i 2 m 2 = \displaystyle\sum_{i = 1}^{k}(\frac{a_i}{m} - p_i)^2 + \displaystyle\sum_{i = k + 1}^{n}\frac{a_i^2}{m^2} =i=1k(maipi)2+i=k+1nm2ai2
= k λ 2 + ∑ i = k + 1 n a i 2 m 2 = k\lambda^2 + \frac{\displaystyle\sum_{i = k + 1}^{n} a_i^2}{m^2} =kλ2+m2i=k+1nai2
= ( ∑ i = 1 k ( a i ) − m ) 2 + k ∑ i = k + 1 n a i 2 m 2 k =\frac{(\displaystyle\sum_{i = 1}^k (a_i) -m)^2 + k\displaystyle\sum_{i = k + 1}^n a_i^2}{m^2k} =m2k(i=1k(ai)m)2+ki=k+1nai2
最后上代码
代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pi 3.1415926
#define mp(x, y) make_pair(x, y)
#define vi vector<int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pair;
const int MAX = 1e4 + 10;
const ll mod = 1e9 + 7;

ll n, m;
ll a[MAX], pre[MAX];

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
bool cmp(const ll &a, const ll &b) { return a > b; }

int main() {
#ifdef ACM_LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	while (~scanf("%lld%lld", &n, &m)) {
		for (int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		sort(a + 1, a + 1 + n, cmp);
		//求前缀和
		pre[0] = -m;
		for (int i = 1; i <= n; i++)
			pre[i] = pre[i - 1] + a[i];
		//找满足的项数
		ll k = n;
		for (int i = 1; i < n; i++)
			if (i * a[i + 1] < pre[i]) {
				k = i;
				break;
			}
		ll p = pre[k] * pre[k], q = m * m * k;
		for (int i = k + 1; i <= n; i++)
			p += k * a[i] * a[i];
		ll gcdd = gcd(p, q);
		p /= gcdd; q /= gcdd;
		if (q == 1 || !p)printf("%lld\n", p);
		else printf("%lld/%lld\n", p, q);
		
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值