51nod_1098_最小方差
阿新 • • 發佈:2018-01-27
algo lac 別人 sin b- i++ nod 變化 -s
若x1,x2,x3......xn的平均數為k。
則方差s^2 = 1/n * [(x1-k)^2+(x2-k)^2+.......+(xn-k)^2] 。
方差即偏離平方的均值,稱為標準差或均方差,方差描述波動程度。
給出M個數,從中找出N個數,使這N個數方差最小。
Input第1行:2個數M,N,(M > N, M <= 10000) 第2 - M + 1行:M個數的具體值(0 <= Xi <= 10000)Output
輸出最小方差 * N的整數部分。
鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1098
都是通過遞推的,但我的方法沒化簡到底,所以比別人慢了點;
先放我的代碼
#include<algorithm> #include<cstdlib> #include<iostream> #include<cstring> #include<cstdlib> #define getrand(a,b) (int)((rand()/33000.0)*((b)-(a)+1))+(a) using namespace std; typedef long long LL; const int maxnn=100+5; const int maxn=100000+5; const int mod=1e9+7; double num[10001];int main() { int m,n;LL ans; double a=0,b=0,k,derta,x;//a:方差*n,b:n個數的和,k:均值 cin>>m>>n; //derta:均值變化量 for(int i=0;i<m;i++){ cin>>num[i]; } sort(num,num+m); // for(int i=0;i<m;i++) // cout<<num[i]<<‘ ‘; // cout<<endl; intf,l;//首位標號 f=0;l=0; for(int i=0;i<n;i++)b+=num[i]; k=b/(double)n; // cout<<k<<endl; while(l<n){ x=num[l]-k; a+=x*x; l++; } l--;ans=a; double x1;//臨時變量 m=m-1; while(l<m){ l++; a-=(num[f]-k)*(num[f]-k); // cout<<a<<‘ ‘;//1 b-=num[f++]; // cout<<b<<‘ ‘;//2 x1=k; k=(b+num[l])/(float)n; // cout<<k<<‘ ‘;//3 derta=k-x1; // cout<<derta<<‘ ‘;//4 a=a-derta*(b-(n-1)*x1)*2+(n-1)*derta*derta; // cout<<a<<‘ ‘;//5 b+=num[l]; // cout<<b<<‘ ‘;//6 a+=(num[l]-k)*(num[l]-k); // cout<<a<<‘ ‘<<endl; if(a<ans)ans=a; } cout<<ans<<endl; return 0; }
別人的較好代碼
#include <iostream> #include<stdio.h> #include<algorithm> #define MAX_N 10001 int a[MAX_N]; using namespace std; int main() { int M,N; scanf("%d%d", &M,&N); for(int i=0; i<M; i++) scanf("%d", a+i); sort(a, a+M); long long sqrSum = 0; long long sum = 0; for(int i=0; i<N; i++) { sqrSum += a[i]*a[i]; sum += a[i]; } long long ans = sqrSum-sum*sum*1.0/N; for(int i=N; i<M; i++) { sqrSum -= a[i-N]*a[i-N]; sum -= a[i-N]; sqrSum += a[i]*a[i]; sum += a[i]; ans = min(ans, (long long)(sqrSum-sum*sum*1.0/N)); } printf("%lld\n", ans); return 0; }
51nod_1098_最小方差