51nod_1098_最小方差

Posted gsimt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod_1098_最小方差相关的知识,希望对你有一定的参考价值。

若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; 
    int f,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_最小方差的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1098 最小方差 排序+前缀和+期望方差公式

51Nod1222 最小公倍数计数 数论 Min_25 筛

51nod1227 平均最小公倍数

51nod1222 最小公倍数计数

51nod1238 最小公倍数之和 V3

学术篇51nod 1238 最小公倍数之和