Codeforces1445D. Divide and Sum

Divide and Sum

题目大意

给定一个长度为(2n)的数组,将数组分成两个长度为n的数组p,q,将p从小到大排序,将q从大到小排序,对于每种分法,(ans=displaystylesum_{i=1}^{n}|p_i-q_i|),现在求总的答案

Solution

考虑将a先从小到大排序后,可以分成前后两块

其中因为p,q的长度是固定的,所以我们可以知道

在p中的左块个数与q中的右块个数相同,在p中的右块个数与在q中的左块个数相同

因为是排序的,所以对于每种方案,一定是右块的数去减左块的数

所以可以把左块的数看成负数,右块的数为正数,将整个数组累加,设和为(tot)

而所有的排列总数是(C_{2n}^{n})

所以总的答案(displaystyle ans=tot cdot C_{2n}^{n})

Code

#include <cstdio>
#include <algorithm>
#define MO 998244353
#define M 300001 
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int n,m,i,a[M];
long long t,ans,f[M];
long long ksm(long long x,int y)
{
    long long sum=1;
    while (y)
    {
        if (y&1) sum=sum*x%MO;
        x=x*x%MO;
        y>>=1;
    }
    return sum;
}
int main()
{
    open("1445D");
    scanf("%d",&n);
    m=n<<1;
    for (i=1;i<=m;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+m+1);
    for (i=1;i<=n;i++)
    {
        ans=(ans+a[i+n]-a[i])%MO;
    }
    f[1]=1;
    for (i=2;i<=m;i++)
        f[i]=f[i-1]*i%MO;
    t=ksm(f[n],MO-2);
    ans=ans*f[m]%MO*t%MO*t%MO;
    printf("%lld",ans);
    return 0;
}
如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.
原文地址:https://www.cnblogs.com/Sport-river/p/13916874.html