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