统计监控数据

题意

输入一行浮点数,总个数是 19 的整数倍。把它们按每 19 个一组拆成若干样本,然后对 19 列特征分别计算 8 个统计量:mean、max、min、ptp(极差)、std(总体标准差)、var(总体方差)、skew(总体偏度)、kurt(总体超峰度)。

所有结果保留两位小数,按特征 0 到特征 18 的顺序输出,每个特征输出 8 个值,用空格分隔。

思路

这题本身不涉及算法设计,纯粹是统计公式的实现。唯一需要注意的是偏度和峰度的定义用的是总体公式,分母是 而不是

数据整理: 读入所有浮点数后,按 19 个一组划分成 个样本。然后对第 列,取出所有样本在该列的值组成数组

基础统计量: mean、max、min 没什么好说的。ptp 就是 max min。总体方差 ,标准差

偏度和峰度怎么算? 先把每个值标准化:,然后:

$$

$$

减 3 是因为正态分布的四阶矩为 3,减去之后得到的是"超峰度"。当 时(所有值相同),偏度和峰度都定义为 0。

一个小细节: 样例里 3 个等差数据的 kurt 是 。用公式验证一下:(标准化后的值), 之和为 2,平均为 ,减 3 得 ……等等,这和 对不上?

别急,标准差是 ,原始数据比如 ,mean ,两个加起来 ,平均 ,减 3 就是 。没错,关键是 不是 ,因为标准差不是 1。

复杂度

  • 时间:,对每列遍历所有样本
  • 空间:,存储所有数据

代码

import sys

def solve():
    data = list(map(float, sys.stdin.read().split()))
    n = len(data) // 19
    samples = []
    for i in range(n):
        samples.append(data[i * 19:(i + 1) * 19])

    results = []
    for col in range(19):
        vals = [samples[row][col] for row in range(n)]
        mean = sum(vals) / n
        mx = max(vals)
        mn = min(vals)
        ptp = mx - mn
        var = sum((x - mean) ** 2 for x in vals) / n
        std = var ** 0.5
        if std == 0:
            skew = 0.0
            kurt = 0.0
        else:
            skew = sum(((x - mean) / std) ** 3 for x in vals) / n
            kurt = sum(((x - mean) / std) ** 4 for x in vals) / n - 3
        results.extend([mean, mx, mn, ptp, std, var, skew, kurt])

    print(' '.join(f'{x:.2f}' for x in results))

solve()
#include <bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    vector<double> data;
    double x;
    while(cin >> x) data.push_back(x);
    int n = data.size() / 19;
    cout << fixed << setprecision(2);
    for(int col = 0; col < 19; col++){
        vector<double> vals(n);
        for(int i = 0; i < n; i++) vals[i] = data[i * 19 + col];
        double mean = 0, mx = vals[0], mn = vals[0];
        for(auto v : vals){ mean += v; mx = max(mx, v); mn = min(mn, v); }
        mean /= n;
        double ptp = mx - mn;
        double var = 0;
        for(auto v : vals) var += (v - mean) * (v - mean);
        var /= n;
        double std_ = sqrt(var);
        double skew = 0, kurt = 0;
        if(std_ != 0){
            for(auto v : vals){
                double z = (v - mean) / std_;
                skew += z * z * z;
                kurt += z * z * z * z;
            }
            skew /= n;
            kurt = kurt / n - 3;
        }
        double res[] = {mean, mx, mn, ptp, std_, var, skew, kurt};
        for(int i = 0; i < 8; i++){
            if(col > 0 || i > 0) cout << ' ';
            cout << res[i];
        }
    }
    cout << endl;
}