题意:
有2n个数,需要把他们分解成两堆,每一堆选取n个数, 总共有种方式。对于每一种方式第一堆从小到大排序,第二堆从大到小排序。 求sum=
问所有的方式的sum之和是多少。
思路:
首先,有一个规律,无论怎么分组,sum值都是固定的。这个需要仔细观察。如果不知道这个规律,这个题就不知道怎么做了。
把sum值求出来,然后乘上方式的总数就行了。求组合数需要逆元,不能直接除。
#pragma warning(disable:4996)
#include<iostream>
#include<algorithm>
#include<map>
#include<cstdio>
#include<set>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 300005;
const ll mod = 998244353;
ll sum, n;
ll a[maxn], fac[maxn];
ll a1[maxn], a2[maxn];
void init() {
fac[0] = 1;
ll i;
for (i = 1; i < maxn; i++)
{
fac[i] = (fac[i - 1] * i) % mod;
}//预处理阶乘
}
ll qpow(ll a, ll c) {
ll ans = 1;
a %= mod;
while (c)
{
if (c & 1)ans = (ans * a) % mod;
a = (a*a) % mod;
c /= 2;
}
return ans;//快速幂主要用来求逆元
}
ll com(ll n, ll m){
return fac[n] * qpow(fac[m] * fac[n - m] % mod, mod - 2) % mod;
//组合数公式,不能直接除,求逆元。
}
bool cmp(ll x, ll y) {
return x > y;
}
int main()
{
ll i, j, ans;
init();
scanf("%lld", &n);
for (i = 1; i <= n; i++)
{
scanf("%lld", &a1[i]);
}
for (i = 1; i <= n; i++)
{
scanf("%lld", &a2[i]);
}
sort(a1 + 1, a1 + 1 + n);
sort(a2 + 1, a2 + 1 + n, cmp);
for (i = 1; i <= n; i++)
{
sum += abs(a1[i] - a2[i]);
sum %= mod;
}//求出固定值sum
ans = com(2 * n, n) * sum % mod;
cout << ans << endl;
return 0;
}