Codeforces Round #680B
大意
给定长度为(2n)的正整数序列,将其分为两个长度相同子列(a,b),将(a)中元素降序排列(b)中升序排列。
求对于所有的排序后的(a_k,b_k),(Sigma_kSigma_i(|a_{ki}-b_{ki}|))的值。
思路
最重要的一点,每一种分划方式得到的(a_k,b_k) ,(Sigma_i(|a_{ki}-b_{ki}|))的值一定相等。
最后答案就是(egin{pmatrix} 2n \ n end{pmatrix} * Sigma_i(|a_i-b_i|))。
现证明每种分划的求和相等。
考虑将划分中的值按其在排序中的位置放到坐标平面上并连接,意义已经标注在图上。
实际的点并不连续,也可能并不单调递减,但不影响思考。
考虑图中的情况。显然存在(k),满足(a_k>b_k)且(a_{k+1}leq b_{k+1})。
( herefore forall i>k,|a_i-b_i| = b_i-a_i)。
将(a_i,b_i)交换((i>k)),得到一组新的序列(a',b') 。如下图。
交换前后显然(Sigma_i(|a_i-b_i|))不变,但是(forall i,j) 有(a_i'geq b_j')。
所以得到(Sigma_i(|a_i-b_i|)=Sigma_i(|a_i'-b_i'|)=c)。
(c)是原序列中前n大之和和前n小之和的差值。
当然,要A掉这题,你还要会逆元和组合数。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
const int mod = 998244353;
int n;
int a[300200];
ll fac(int N) {
ll ans = 1;
for(ll i=2; i<=N; i++)
ans = (ans*i)%mod;
return ans;
}
ll ksm(ll x, int c) {
ll ans = 1;
ll tmp = x;
while(c) {
if(c&1) ans = (ans*tmp) % mod;
c >>= 1;
tmp = (tmp*tmp) % mod;
}
return ans;
}
ll counter(int N) {
return (fac(2*N)*ksm((fac(N)*fac(N))%mod, mod-2)) % mod;
}
int main() {
cin >> n;
for(int i=1; i<=2*n; i++) cin >> a[i];
sort(a+1, a+1+2*n);
ll pre = 0;
for(int i=1; i<=n; i++)
pre = (pre + a[n+i] - a[i]) % mod;
cout << (pre*counter(n)) % mod;
return 0;
}