EOJ 2020.03月赛题解 | E.钢琴演奏家(组合数学 C++)

来源https://acm.ecnu.edu.cn/contest/255/problem/D/
在这里插入图片描述

思路
对数组排序后,每次选一个最大数,然后再从它的左侧选m-1个数,通过组合公式可以得到答案为
i=mnai(m1i1) \sum_{i =m} ^n a_i \binom{m-1}{i-1}

说明:

  1. 数组元素相同时,我们认为左边的数比右边的数小
  2. 这题数据范围看着恐怖,TNlogNT * N logN 好像会超时,但实际可以过
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 1e6 + 7, mod = 1e9 + 7;

int a[N];
LL fact[N], infact[N]; // 阶乘数组最好用 long long 来存

// 快速幂
int qmi(int a, int k, int p) {
    int res = 1;
    while (k) {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}

// 预处理阶乘
void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i <= N; i++) {
        fact[i] = fact[i - 1] * i % mod;
        infact[i] = infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
}

int main() {
    int T;
    cin >> T;

    init();

    while (T --) {
        int n, m;
        cin >> n >> m;
        
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }

        sort(a + 1, a + n + 1);
		
		// 计算组合公式
        int res = 0;
        for (int i = m; i <= n; i ++) {
            int x = i - 1, y = m - 1;
            res = (res % mod + a[i] * 1ll * fact[x] % mod * infact[x - y] % mod * infact[y] % mod) % mod;
        }
        cout << res << endl;
    }

    return 0;
}
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 鲸 设计师: meimeiellie
应支付0元
点击重新获取
扫码支付

支付成功即可阅读