EOJ Monthly 2020.3 D. 钢琴演奏家

规律还是比较容易得到的,先排序确定一个数后,后面的数字用组合数进行选择,累计一下贡献。但是这个地方需要进行一下优化了,组合数前后两项是有关系的,可以递推一下,还要预处理一下阶乘。这样就降复杂度了,另外还是多取几次模吧。

#include <iostream>
#include <malloc.h>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <cstring>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 2e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const double PI = 3.14159;
const double eps = 1e-8;
const int mod = 1e9 + 7;
struct Node
{
    LL val;
    int id;
} a[maxn];
LL b[maxn];
LL qpow(LL a, LL b, LL c)
{
    LL ans = 1;
    while (b)
    {
        if (b & 1)
            ans = ans * a % c;
        a = a * a % c;
        b = b >> 1;
    }
    return ans;
}
LL Inv(LL a, LL p)
{
    return qpow(a, p - 2, p);
}
bool cmp(Node a, Node b)
{
    return a.val > b.val;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    IO;
    int T;
    int n, m;
    cin >> T;
    b[0] = 1;
    b[1] = 1;
    for (LL i = 2; i <= 1e6; i++)
    {
        b[i] = b[i - 1] * i % mod;
    }
    while (T--)
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i].val;
            a[i].id = i;
        }
        sort(a + 1, a + n + 1, cmp);
        LL ans = 0;
        LL t = 1;
        for (LL i = n - 1; i >= n - m + 1; i--)
        {
            t = t * i % mod;
        }
        t = (t % mod * Inv(b[m - 1], mod) % mod) % mod;
        LL p1 = n - 1;
        LL p2 = n - m + 1;
        for (int i = 1; i <= n; i++)
        {
            if (n - i >= m - 1)
            {
                ans = (ans % mod + (a[i].val % mod * t % mod) % mod) % mod;
                t = (t % mod * Inv(p1, mod) % mod) % mod;
                --p2;
                t = (t % mod * p2 % mod) % mod;
                --p1;
            }
            else
                break;
        }
        cout << ans << endl;
    }
    return 0;
}
发布了81 篇原创文章 · 获赞 29 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/105001859