题意:给出一些点,要求这些点的力距的最小值
思路:首先对点进行排序,这样得到的最后的解一定是连续的m=n-k个数。假设这m个点的重心是mid,每个点的位置是p,那么这些点的力距是
sigma p^2 - sigma(2*p*mid)+m*mid^2(将每个点的力距按照平方展开,然后求和)
这里面平方和与一次方的和可以直接求
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define COUNT sum2[j]-sum2[i-1]-2*mid*(sum[j]-sum[i-1])+mid*mid*k
double pos[50005];
double sum[50005];
double sum2[50005];
int main()
{
//freopen("data.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;++i)
{
scanf("%lf",&pos[i]);
}
if(n==k||n==k+1)
{
printf("0\n");
continue;
}
sort(pos,pos+n);
for(int i=0;i<n;++i)
{
if(i==0)
{
sum[i]=pos[i];
sum2[i]=pos[i]*pos[i];
}
else
{
sum[i]=pos[i]+sum[i-1];
sum2[i]=pos[i]*pos[i]+sum2[i-1];
}
}
double ans;
k=n-k;
for(int i=0;i<n;++i)
{
int j=i+k-1;
if(j==n)break;
double mid=sum[j]-((i-1>=0)?sum[i-1]:0);
mid=mid/k;
if(i==0){
ans=COUNT;
}
else
{
ans=min(ans,COUNT);
}
}
printf("%.9lf\n",ans);
}
return 0;
}