1. 程式人生 > >HDU - 5073 Galaxy(數學)

HDU - 5073 Galaxy(數學)

turn -a min print mes tps div 完成 return

題目

題意: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\n"); 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\n",ans); } return 0; }

HDU - 5073 Galaxy(數學)