1 条题解

  • 0
    @ 2024-11-18 21:45:10
    MaximumAverageSetsMaximum Average Sets

    首先,将给定物品的价值按降序排序,记为 v0v1vN1v_0​≥v_1​≥⋯≥v_{N−1​}。

    接着,固定选择的物品数量为 KK 进行分析。
    此时,能够使选择的物品的平均价值达到最大值的集合为 v0,v1,,vK1{v_0​,v_1​,…,v_{K−1}​}
    进一步比较选择 KK 个物品时的平均值和选择 K+1K+1 个物品时的平均值的差异:

    \begin{equation} \frac{1}{K} \sum_{i=0}^{K-1} v_i - \frac{1}{K+1} \sum_{i=0}^K v_i = \frac{(K+1)}{K} \sum_{i=0}^{K-1} v_i - \sum_{i=0}^K v_i = \sum_{i=0}^{K-1} (v_i - v_K) \geq 0 \end{equation}

    因此,可以得出结论:当选择 KK 个物品时,平均价值的最大值一定大于或等于选择 K+1K+1 个物品时的平均价值的最大值。
    所以,选择 AA 个物品时的最大平均价值,就是答案的第一行。


    接下来,计算能够使物品平均价值达到最大值的选择方式的数量。
    这时,根据上位 AA 个物品的价值 v0,v1,,vA1{v0​,v1​,…,vA−1​},可以分以下几种情况进行讨论:

    1. 当 v0!=vA1v_0​ != v_{A-1}​ 时

    在这种情况下,随着选择的物品数量增加,选择的物品的平均值会逐渐下降。
    因此,只需计算出由 v0,v1,,vA1{v0​,v1​,…,vA−1​} 构成的集合的选择方式。
    v0=vi(0iN1)v0​=vi​(0≤i≤N−1) 的个数为 XX
    v0=vi(0iA1)v0​=vi​(0≤i≤A−1) 的个数为 YY
    则答案为 $(YX​)。

    2. 当 v0==vA1v_0​ == v_{A-1}​ 时

    在这种情况下,即使增加选择的物品数量,选择的物品平均值仍然可能保持最大值。
    这种情况发生在所有选择的物品的价值都等于 v0​v_0​ ​时。
    此时,物品的选择数量可以在 A​A​ 到 B​B​ 的范围内变化,
    因此,设 v0=vi(0iN1)v0​=vi​(0≤i≤N−1) 的个数为 X​X​,
    答案为:

    i=AB(iX)i=A∑B​(iX​)


    组合数 nCm(0n,mN)nCm(0≤n,m≤N) 可以利用帕斯卡三角形进行预计算,时间复杂度为 O(N2)O(N2)

    综上所述,算法的总时间复杂度为:

    • 排序:O(NlogN)O(NlogN)
    • 计算平均值:O(N)O(N)
    • 帕斯卡三角形的预计算:O(N2)O(N2)
    • 计数选择方式:O(N)O(N)

    因此,总时间复杂度为 O(N2)O(N2),能够在时间限制内完成。

    另外,还存在基于阶乘和逆元预计算的时间复杂度为 O(NlogN)O(NlogN) 的解法(这里省略具体细节)。


    C++ 示例代码(利用帕斯卡三角形进行组合数的预计算)

    using ll = long long;
    using R = double;
    
    // 组合数表
    ll C[51][51];  // C[n][k] -> nCk
    
    void comb_table(int N) {
        for (int i = 0; i <= N; ++i) {
            for (int j = 0; j <= i; ++j) {
                if (j == 0 || j == i) {
                    C[i][j] = 1LL;
                } else {
                    C[i][j] = (C[i-1][j-1] + C[i-1][j]);
                }
            }
        }
    }
    
    int main(void) {
        int N, A, B;
        cin >> N >> A >> B;
    
        const int NMAX = 50;
        ll v[NMAX];
    
        for (int i = 0; i < N; ++i) {
            cin >> v[i];
        }
    
        comb_table(N);
        sort(v, v + N);
        reverse(v, v + N);
    
        R max_average = 0.0;
        for (int i = 0; i < A; ++i) {
            max_average += v[i];
        }
        max_average /= A;
    
        int a_th_val_num = 0, a_th_val_pos = 0;
        for (int i = 0; i < N; ++i) {
            if (v[i] == v[A - 1]) {
                a_th_val_num++;
                if (i < A) {
                    a_th_val_pos++;
                }
            }
        }
    
        ll cnt = 0LL;
        if (a_th_val_pos == A) {
            for (a_th_val_pos = A; a_th_val_pos <= B; ++a_th_val_pos) {
                cnt += C[a_th_val_num][a_th_val_pos];
            }
        } else {
            cnt += C[a_th_val_num][a_th_val_pos];
        }
    
        cout.precision(20);
        cout << fixed << max_average << endl;
        cout << cnt << endl;
    
        return 0;
    }
    

    信息

    ID
    5487
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    2
    上传者