题意:
给你n个星球,现在能移动k个星球到任意地方,求移动之后的I= sum(di*di) (i=1,2,3..,n), di为星球i到重心的距离
方法:
我们可以很容易想到不会移动的n-k个星球一定会是连续的,然后我们枚举这连续的n-k星球即可,设移动前星球i的位置为ci, ai为ci的前i项和,bi为ci前i的平方和
则我们可以快速算出移动之后的I
PS:
di is the distance form star i to the mass of center. 我当时以为是重心,然后这题就被我想的复杂了。
di是i到重心的距离。。。。
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 55555
#define eps 1e-12
int c[maxn];
double a[maxn], b[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n, k;
scanf("%d %d",&n,&k);
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
int num;
for(int i= 1; i<= n; i++)
scanf("%d",&c[i]);
sort(c+1, c+n+1);
for(int i= 1; i<= n; i++)
{
a[i]= a[i-1]+ 1.0*c[i];
b[i]= b[i-1]+ 1.0*c[i]*c[i];
}
if(k== n)
{
printf("0\n");
continue;
}
double ans= 0;
for(int ll= 1; ll<= k+1; ll++)
{
int rr= ll+ n- k- 1;
double t= (a[rr]- a[ll-1])/(n-k);
double s= ( b[rr]- b[ll-1] )+ (n-k)*t*t - 2*t*(a[rr]- a[ll-1]);
if(ll== 1)
ans= s;
else
ans= min(ans, s);
}
printf("%.10lf\n",ans);
}
return 0;
}