题意:n个点,运行移动k个点到任何位置,允许多个点在同一位置上。求移动k个点后,所有点到整体中心的距离的平方和最小。
分析:这题题目真的有点迷。。。一开始看不懂。得知最后是选取一个中心,于是看出来了方差的味道。这里便是求移动完成后方差的最小值,那么只需找连续n-k个最小的序列,然后把其他k个点都放在中心,即为正解。注意到(a[i]-ave)^2=a^2+ave^2-2*a*ave,可以在此化简代码。详情看代码。
#include <cstdio> #include <iostream> #include <cmath> #include <algorithm> #include <cstdlib> #include <cstring> #include <queue> #define ll long long using namespace std; const int maxn = 50050; int main(){ int t,n,k; ll a[maxn]; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); if(n==k){ printf("0.000000000 "); continue; } sort(a+1,a+1+n); ll sum=0,tot=0; for(int i=1;i<=n-k;i++){ sum+=a[i]; tot+=a[i]*a[i]; } double ave=(sum*1.0)/(n-k); double ans=ave*ave*(n-k)+tot-2*ave*sum; for(int i=2;i<=k+1;i++){ sum=sum-a[i-1]+a[n-k+i-1]; tot=tot-a[i-1]*a[i-1]+a[n-k+i-1]*a[n-k+i-1]; ave=(sum*1.0)/(n-k); double t=ave*ave*(n-k)+tot-2*ave*sum; ans=min(t,ans); } printf("%.9lf ",ans); } return 0; }