# [2019牛客网多校训练第1场]Euclidean Distance

2019-07-18 22:40:56  阅读：114  来源： 互联网

Bobo has a point A in the $n$n dimension real space $R_n$Rn​, whose coodinate is $(a_1/m,a_2/m,…,a_n/m)$(a1​/m,a2​/m,…,an​/m) where $a_i$ai​ and m are both integers. He wants to find another point $P=(p_1,p_2,…,p_n)$P=(p1​,p2​,…,pn​) meeting the following requirements.

• $p_1,p_2,…,p_n∈R$p1​,p2​,…,pn​∈R. That is, they are real numbers.
• $p_1,p_2,…,p_n≥0$p1​,p2​,…,pn​≥0
• $p_1+p_2+⋯+p_n=1$p1​+p2​+⋯+pn​=1
• The (squared) Euclidean distance between $P$P and $A$A, which is $∥A−P∥^2=∑n_i=\sum(a_i/m−p_i)^2$∥A−P∥2=∑ni​=∑(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$n integers $a_1,a_2,…,a_n$a1​,a2​,…,an​.

• $1≤n≤10^4$1≤n≤104
• $1≤m≤10^3$1≤m≤103
• $−m≤a_i≤m$−m≤ai​≤m
• The sum of $n$n does not exceed $5×10^5$5×105.

For each test case, print a fraction which denotes the result.

1 1
0
2 3
1 2
3 10
1 -2 3


1
0
16/75


$p_1,p_2,…,p_n≥0$p1​,p2​,…,pn​≥0
$p_1+p_2+⋯+p_n=1$p1​+p2​+⋯+pn​=1

$a_i$ai​从大到小排序，枚举将最大的$i$i个$a_i$ai​处理成同一个值，我们把前i个$a_i$ai​处理成同一个值的时候，假设代价为每个数字和它的初始值的绝对值之差，消耗的代价总和不能超过$m$m。当不能继续放置的时候（设总代价为k），我们就可以将剩余的$m-k$m−k的代价均摊到所有非负的$a_i$ai​值上，然后他们对答案分子的贡献就是$(m-k-st*v)^2$(m−k−st∗v)2(st为处理成同一个值的$a_i$ai​个数,$v$v那$st$st个$a_i$ai​处理成的同一个值)，剩余的每个$a_i$ai​对答案分子的贡献就是$st*a[i]*a[i]$st∗a[i]∗a[i]，分母的值为$st*m*m$st∗m∗m

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
ll a[10004];
ll ans,m;
int n;
int w33ha(){
ans=0;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+n+1,greater<int>());
ll nd=0;
for(int i=1;i<=n;i++){
if(i<n&&(a[i]-a[i+1])*i+nd<=m){
nd+=(a[i]-a[i+1])*i;
}
else{
ans=(m-nd-i*a[i])*(m-nd-i*a[i]);
for(int j=i+1;j<=n;j++){
ans+=i*a[j]*a[j];
}
ll d,p=i*m*m;
if(ans==0)return puts("0");
d=__gcd(ans,p);
ans/=d;p/=d;
if(p==1)printf("%lld\n",ans);
else printf("%lld/%lld\n",ans,p);
return 0;
}
}
return 0;
}
int main(){
while(scanf("%d%lld",&n,&m)!=EOF)w33ha();
return 0;
}