Codeforces Round #680 (Div. 1, based on Moscow Team Olympiad) B. Divide and Sum(思维+组合数)

题目链接:https://codeforc.es/contest/1444/problem/B

You are given an array a of length 2n. Consider a partition of array a into two subsequences p and q of length n each (each element of array a should be in exactly one subsequence: either in p or in q).

Let’s sort p in non-decreasing order, and q in non-increasing order, we can denote the sorted versions by x and y, respectively. Then the cost of a partition is defined as f(p,q)=∑ni=1|xi−yi|.

Find the sum of f(p,q) over all correct partitions of array a. Since the answer might be too big, print its remainder modulo 998244353.

Input
The first line contains a single integer n (1≤n≤150000).

The second line contains 2n integers a1,a2,…,a2n (1≤ai≤109) — elements of array a.

Output
Print one integer — the answer to the problem, modulo 998244353.

Examples

input

1
1 4

output

6

input

2
2 1 2 1

output

12

input

3
2 2 2 2 2 2

output

0

input

5
13 8 35 94 9284 34 54 69 123 846

output

2588544

题意

给定一个数组a,有 2n 个数,分成两个数组p ,q :p是非递减,q 是非递增。f ( p , q ) = ∑ ∣ p i − q i ∣ ,计算所有 f ( p , q ) 的和。

分析

我们先将 a 数组排序,可以发现无论怎么分组,1 ~ n 号元素不可能匹配到一起,同理 n + 1 ~ n + n 号元素也不可能组合到一起。设1 ~ n 号元素和为 x ,n + 1 ~ n + n 号元素和为 y ,我们可以发现无论怎么组合,每一种组合对答案的贡献值都为 y - x 。
总共有 C(2 * n, n) 种组合,那么答案就是 C(2 * n, n) * (y - x) 。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 998244353;
ll n;
ll a[300007];
ll sum[300007];
ll f[300007];

ll qm(ll x,ll y)
{
	ll res = 1;
	while(y)
	{
		if(y & 1) res = (res * x) % mod;
		x = (x * x) % mod;
		y >>= 1;
	}
	return res % mod;
}

ll C(ll x,ll y)
{
	return f[x] * qm(f[y] * f[x - y] % mod, mod - 2) % mod;
}

int main()
{
	f[0] = 1;
	for(ll i=1;i<=300000;i++) f[i] = f[i - 1] * i % mod;
	scanf("%lld",&n);
	for(ll i=1;i<=2*n;i++) scanf("%lld",&a[i]);
	sort(a + 1, a + 1 + 2 * n);
	sum[1] = a[1];
	for(ll i=2;i<=2*n;i++) sum[i] = (sum[i - 1] + a[i]) % mod;
	ll tmp = C(2 * n, n) % mod;
	ll ans = ((sum[2 * n] + mod - sum[n]) % mod + mod -  sum[n]) % mod * tmp % mod;
	printf("%lld",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值