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

链接:https://ac.nowcoder.com/acm/contest/881/C
来源:牛客网

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

  • p1,p2,,pnRp_1,p_2,…,p_n∈Rp1​,p2​,…,pn​∈R. That is, they are real numbers.
  • p1,p2,,pn0p_1,p_2,…,p_n≥0p1​,p2​,…,pn​≥0
  • p1+p2++pn=1p_1+p_2+⋯+p_n=1p1​+p2​+⋯+pn​=1
  • The (squared) Euclidean distance between PPP and AAA, which is AP2=ni=(ai/mpi)2∥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 nnn integers a1,a2,,ana_1,a_2,…,a_na1​,a2​,…,an​.

  • 1n1041≤n≤10^41≤n≤104
  • 1m1031≤m≤10^31≤m≤103
  • maim−m≤a_i≤m−m≤ai​≤m
  • The sum of nnn does not exceed 5×1055×10^55×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

题意:
给定nnn个数字a1a_1a1​到ana_nan​,要求nnn个实数p1p_1p1​到pnp_npn​,使得(ai/mpi)2\sum(a_i/m−p_i)^2∑(ai​/m−pi​)2最小
并且满足:
p1,p2,,pn0p_1,p_2,…,p_n≥0p1​,p2​,…,pn​≥0
p1+p2++pn=1p_1+p_2+⋯+p_n=1p1​+p2​+⋯+pn​=1

输出最小的答案,用最简分数表示。

题解:
由于aia_iai​互相之间不会影响,所以顺序可以打乱。
aia_iai​从大到小排序,枚举将最大的iii个aia_iai​处理成同一个值,我们把前i个aia_iai​处理成同一个值的时候,假设代价为每个数字和它的初始值的绝对值之差,消耗的代价总和不能超过mmm。当不能继续放置的时候(设总代价为k),我们就可以将剩余的mkm-km−k的代价均摊到所有非负的aia_iai​值上,然后他们对答案分子的贡献就是(mkstv)2(m-k-st*v)^2(m−k−st∗v)2(st为处理成同一个值的aia_iai​个数,vvv那ststst个aia_iai​处理成的同一个值),剩余的每个aia_iai​对答案分子的贡献就是sta[i]a[i]st*a[i]*a[i]st∗a[i]∗a[i],分母的值为stmmst*m*mst∗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;
}
上一篇:python实验报告二


下一篇:queryList实现分页参数接受的采集