ARC128F 题解
Last Update:
非常好题目,不会第一步。
令
考虑
把所有数按照
不妨换个角度考虑,对于 A 选的一个位置集合
那么贪心策略就容易得出了。维护一个优先队列,按
观察上述过程,发现其只取决于
但”第
考虑计算
其中红边表示扳回
这种不断对
因为
设
引理
证明:方案数等于
那么,路径不越过直线
所以,路径纵坐标最小值
所以最小值
那么我们就可以列出
那么最后答案就是
时间复杂度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38const int N = 1e6 + 5,P = 998244353;
inline void Plus(int &x,const int &y) { x += y;if(x >= P) x -= P;}
int n,a[N];
int fac[N],ifac[N];
int bs[N];
inline void init(int n)
{
fac[0] = 1;
for(int i = 1;i <= n;i++) fac[i] = 1ll * fac[i - 1] * i % P;
ifac[1] = 1;
for(int i = 2;i <= n;i++) ifac[i] = 1ll * ifac[P % i] * (P - P / i) % P;
ifac[0] = 1;
for(int i = 1;i <= n;i++) ifac[i] = 1ll * ifac[i - 1] * ifac[i] % P;
}
inline int C(int n,int m) { if(n < 0 || m < 0 || n < m) return 0;return 1ll * fac[n] * ifac[m] % P * ifac[n - m] % P;}
int g[N];
int main()
{
read(n);
for(int i = 1;i <= n;i++) read(a[i]);
sort(a + 1,a + n + 1,greater<int>());
n /= 2;
init(n + n);
for(int i = 2 * n;i >= 0;i--)
bs[i] = bs[i + 2],Plus(bs[i],C(n + n,i));
for(int m = 0;m <= n + n;m++)
{
int p = max(0,n - m);
g[m] = 1ll * (n - p) * C(n + n,m + p + p) % P;
Plus(g[m],P - (m + p + p + 2 <= n + n ? bs[m + p + p + 2] : 0));
g[m] = 1ll * g[m] * fac[m] % P * fac[n + n - m] % P;
}
int ans = 0;
for(int i = 1;i <= n + n;i++)
Plus(ans,1ll * a[i] * (g[i] - g[i - 1] + P) % P);
cout << ans << endl;
return 0;
}