C.Euclidean Distance
题目描述
Bobo has a point A in the n dimension real space
R
n
\mathbb{R}^n
Rn, whose coodinate is
(
a
1
/
m
,
a
2
/
m
,
…
,
a
n
/
m
)
(a_1 / m, a_2 / m, \dots, a_n / m)
(a1/m,a2/m,…,an/m) and m are both integers. He wants to find another point P =
(
p
1
,
p
2
,
…
,
p
n
)
(p_1, p_2, \dots, p_n)
(p1,p2,…,pn) meeting the following requirements.
p
1
,
p
2
,
…
,
p
n
∈
R
p_1, p_2, \dots, p_n \in \mathbb{R}
p1,p2,…,pn∈R.That is, they are real numbers.
- p 1 , p 2 , … , p n ≥ 0 p_1, p_2, \dots, p_n \geq 0 p1,p2,…,pn≥0
- p 1 + p 2 + ⋯ + p n = 1 p_1 + p_2 + \dots + p_n = 1 p1+p2+⋯+pn=1
- The (squared) Euclidean distance between P and A, which is ∥ A − P ∥ 2 2 = ∑ i = 1 n ( a i / m − p i ) 2 \|A - P\|_2^2 = \sum_{i = 1}^n (a_i / m - p_i)^2 ∥A−P∥22=∑i=1n(ai/m−pi)2 , is minimized.
It can be proved the minimum is always a rational number. Print the squared distance in fraction. Note to print an integer n as n instead of n/1.
输入描述:
The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains two integers n and m.
The second line contains n integers
a
1
,
a
2
,
…
,
a
n
a_1, a_2, \dots, a_n
a1,a2,…,an
1
≤
n
≤
1
0
4
1 \leq n \leq 10^4
1≤n≤104
1
≤
m
≤
1
0
3
1 \leq m \leq 10^3
1≤m≤103
−
m
≤
a
i
≤
m
-m \leq a_i \leq m
−m≤ai≤m
The sum of n does not exceed
5
×
1
0
5
5 \times 10^5
5×105
.
输出描述:
For each test case, print a fraction which denotes the result.
示例1
输入
1 1
0
2 3
1 2
3 10
1 -2 3
输出
1
0
16/75
题目大意:
给定 m 和 n 个整数 ai,
−
m
≤
a
i
≤
m
−m≤a_i≤m
−m≤ai≤m,求
∥
A
−
P
∥
2
2
=
∑
i
=
1
n
(
a
i
/
m
−
p
i
)
2
\|A - P\|_2^2 = \sum_{i = 1}^n (a_i / m - p_i)^2
∥A−P∥22=∑i=1n(ai/m−pi)2在约束条件
p
1
+
p
2
+
⋯
+
p
n
=
1
p_1 + p_2 + \dots + p_n = 1
p1+p2+⋯+pn=1,
p
1
,
p
2
,
…
,
p
n
≥
0
p_1, p_2, \dots, p_n \geq 0
p1,p2,…,pn≥0 下的最小值。
思路:
看大佬博客
听说标程是拉格朗日乘子法做的,但是查了几篇博客都没有用拉格朗日乘子法。
ac_code:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 7;
int n, m;
LL a[maxn];
int main() {
while(~scanf("%d%d",&n,&m)){
for(int i = 1;i<=n;++i){
scanf("%lld",&a[i]);
}
sort(a+1,a+n+1,[](int a,int b){return a>b;});
LL idx=n;
LL las=m;
for(int i=1;i<n;++i){
if(i*abs(a[i+1]-a[i])>las){
idx=i;
break;
}else{
las-=i*abs(a[i+1]-a[i]);
}
}
LL num1=1LL*(idx*a[idx]-las)*(idx*a[idx]-las);
LL num2=1LL*idx*m*m;
for(int i=idx+1;i<=n;++i){
num1+=1LL*a[i]*a[i]*idx;
}
LL tmp=__gcd(num1,num2);
num1/=tmp,num2/=tmp;
if(num2==1) printf("%lld\n",num1);
else printf("%lld/%lld\n",num1,num2);
}
return 0;
}