• 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;
    }
    
    如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.
  • 相关阅读:
    二逼平衡树(树套树)
    NOI2010 超级钢琴
    SDOI2011 消耗战
    HNOI2013 游走
    [SDOI2010]外星千足虫
    [UVA 11374]Airport Express
    [Luogu P1354]房间最短路问题
    [Luogu P2296][NOIP 2014]寻找道路
    高精度算法
    洛谷红名+AC150祭
  • 原文地址:https://www.cnblogs.com/Sport-river/p/13916874.html
Copyright © 2020-2023  润新知