话说这题读起来真费劲啊,估计很多人做不出来就是因为题读不懂......

从题目中提取的几点关键点:

题目背景就是银河系(Rho Galaxy)中的星球都是绕着他们的质心(center of mass)转的(妈蛋就是这里啊,质心是个什么鬼...,其实就是所有点的值的算术平均值)。

现在你可以从一个银河系中的所有星球中转移其中的k个(具体这个转移的意思你可以理解成把他们移到剩下星球的质心上,这样对剩余的整体不会产生影响,当然这也等价于把这k个星球直接删了),然后使剩下的星球让这个The moment of inertia I值最小,计算公式是

其中wi是每个星球的重量,视为单位1,di是星球i到质心的距离(di-d0)。

这样看来I值就是(d1-d0)2 + (d2-d0)2 + ... + (dn-k-d0)2

这不就是标准差吗,当然标准差就是方差的平方,而方差越小表示分布越集中,也就是说,这些星球越连续,这个I值就会越小。

因此这里也用到了贪心的思想。

需要注意的一点是,当n=k时,可以直接输出0,因为这孩子把所有星球都弄到质心去了2333333...

 

附代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn = 500005;
10 ll a[maxn];
11 
12 int main()
13 {
14     int T; scanf("%d", &T);
15     while(T--)
16     {
17         int n, k; scanf("%d%d", &n, &k);
18         for(int i = 0; i < n; i++)
19             scanf("%I64d", &a[i]);
20         sort(a, a+n);
21         ll sum1, sum2; sum1 = sum2 = 0;
22         double cen, ans;
23         if(n == k)
24         {
25             for(int i = 0; i < n; i++)
26             {
27                 sum1 += a[i]*a[i];
28                 sum2 += a[i];
29             }
30             cen = (double)sum2/n;
31             ans = sum1+n*cen*cen-2*cen*sum2;
32             printf("%.10lf\n", ans);
33             //cout << ans << endl;
34             continue ;
35         }
36         for(int i = 0; i < n-k; i++)
37         {
38             sum1 += a[i]*a[i];
39             sum2 += a[i];
40         }
41         cen = 1.0*sum2/(n-k);
42         ans = sum1+(n-k)*cen*cen-2*cen*sum2;
43         int pos = 0;
44         double min_ = ans;
45         for(int i = 0; i < k; i++)
46         {
47             sum1 = sum1-a[i]*a[i]+a[n-k+i]*a[n-k+i];
48             sum2 = sum2-a[i]+a[n-k+i];
49             cen = 1.0*sum2/(n-k);
50             ans = sum1+(n-k)*cen*cen-2*cen*sum2;
51             min_ = min(min_, ans);
52         }
53         printf("%.10lf\n", min_);
54     }
55     return 0;
56 }
hdu 5037