传送门(偷来的)
这题挺不错,写一写题解
考试的时候有些想法,方向还算正确吧
但还是没想出来
对于某个数
a
[
i
]
a[i]
a[i],如果它在第j轮被肝掉,那么它的贡献是
a
[
i
]
∗
(
n
−
j
+
1
)
∗
情
况
数
a[i]*(n-j+1)*情况数
a[i]∗(n−j+1)∗情况数
这个情况数是第i个数在第j轮被肝掉的情况数,但是不好求
用前缀和思想第i个数在第j轮被肝掉的情况数=第i个数在
前
j
前j
前j轮被肝掉的情况数-第i个数在
前
(
j
−
1
)
前(j-1)
前(j−1)轮被肝掉的情况数,就好啦
枚举第i个数,枚举j轮
令
m
表
示
当
前
第
j
轮
共
有
m
个
数
,
那
么
m
=
m
i
n
(
n
,
k
+
j
−
1
)
m表示当前第j轮共有m个数,那么m=min(n,k+j-1)
m表示当前第j轮共有m个数,那么m=min(n,k+j−1)
再令
s
u
m
表
示
前
j
轮
的
情
况
数
,
l
a
s
t
表
示
前
(
j
−
1
)
轮
的
(
由
上
一
个
j
的
s
u
m
赋
值
给
l
a
s
t
)
sum表示前j轮的情况数,last表示前(j-1)轮的(由上一个j的sum赋值给last)
sum表示前j轮的情况数,last表示前(j−1)轮的(由上一个j的sum赋值给last)
令
l
l
l枚举当前比a[i]小的数的个数,那么l的上界是j-1,因为最多(j-1)个数比a[i]小,才能使
a
[
i
]
a[i]
a[i]在前j轮被干掉
计算sum:
s
u
m
=
m
!
∗
(
n
−
m
)
!
∗
∑
l
=
0
j
−
1
(
C
i
−
1
l
∗
C
n
−
i
m
−
j
−
1
)
sum=m!*(n-m)!*\sum_{l=0}^{j-1}(C_{i-1}^{l}*C_{n-i}^{m-j-1})
sum=m!∗(n−m)!∗∑l=0j−1(Ci−1l∗Cn−im−j−1)
累计ans:
a
n
s
+
=
(
s
u
m
−
l
a
s
t
)
∗
a
[
i
]
∗
(
n
−
j
+
1
)
ans+=(sum-last)*a[i]*(n-j+1)
ans+=(sum−last)∗a[i]∗(n−j+1)
Code:
#include <bits/stdc++.h>
#define maxn 1010
#define LL long long
#define qy 1000000007
using namespace std;
int n, k, a[maxn], c[maxn][maxn], fact[maxn], ans;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), k = read();
for (int i = 1; i <= n; ++i) a[i] = read();
sort(a + 1, a + 1 + n);
for (int i = 0; i <= n; ++i){
c[i][0] = 1;
for (int j = 1; j <= i; ++j)
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % qy;
}
fact[0] = 1;
for (int i = 1; i <= n; ++i) fact[i] = 1LL * fact[i - 1] * i % qy;
for (int i = 1; i <= n; ++i)
for (int j = 1, last = 0; j <= n; ++j){
int m = min(n, k + j - 1), sum = 0;
for (int l = 0; l <= j - 1; ++l)
(sum += 1LL * c[i - 1][l] * c[n - i][m - l - 1] % qy) %= qy;
sum = 1LL * sum * fact[n - m] % qy * fact[m] % qy;
(ans += 1LL * (sum - last + qy) * (n + 1 - j) % qy * a[i] % qy) %= qy;
last = sum;
}
printf("%d\n", ans);
return 0;
}
博客给出一道题的题解。对于数a[i],若在第j轮被处理,其贡献为a[i]*(n - j + 1)*情况数。利用前缀和思想求情况数,通过枚举第i个数和j轮,结合相关变量计算情况数并累计答案。
2631

被折叠的 条评论
为什么被折叠?



