zoukankan      html  css  js  c++  java
  • Codeforces Round #680 (Div. 1)

    Codeforces Round #680 (Div. 1)

    Codeforces Round #680 (Div. 1, based on Moscow Team Olympiad)

    A.(思维+质因分解)

    题解见注释

    /*
    O(n)求1-n逆元:前提:p是素数
    inv[i]=(p-p/i)*inv[p%i]%p
    prove. Let t=p/i,k=p%i
    t*i+k=0 (mod p)
    -t*i =k(mod p)
    两边同除以ik,-t*inv[k]=inv[i] (mod p)
    因此 inv[i]=(p-t)*inv[k] (mod p)
    */
     fac[0]=1;for(int i=1;i<maxn;i++) 
         fac[i]=fac[i-1]*i%mod;//n!
     inv[1]=1;for(int i=2;i<maxn;i++) 
         inv[i]=inv[mod%i]*(mod-mod/i)%mod;//O(n)求1-n的逆元
     for(int i=2;i<maxn;i++) 
            inv[i]=inv[i-1]*inv[i]%mod;
    
    

    B.

    我感觉这题很精彩,主要有两个点:

    1.首先是一个结论,就是分割方式不影响最后这段求和后的f。先把a数组排序,前半段属于L,后半段属于R, |qi-pi|,必然一个数属于L,一个数属于R,于是求和的时候就可以前半段的数取负数,后半段的数取正数,相加求和。

    这个证明如下,反证法,不妨设两个都属于前半段。

    下标小于pi的数有px个,下标大于qi的有qx个,px<n,qi>=n,无论如何这两个数都碰不上面,产生矛盾。也可以看cf的官方题解。

    2.就是O(n)求逆元,学习√

    综上最后答案ans=一段求和C[2n][n];

    /*
    O(n)求1-n逆元:前提:p是素数
    inv[i]=(p-p/i)*inv[p%i]%p
    prove. Let t=p/i,k=p%i
    t*i+k=0 (mod p)
    -t*i =k(mod p)
    两边同除以ik,-t*inv[k]=inv[i] (mod p)
    因此 inv[i]=(p-t)*inv[k] (mod p)
    */
     fac[0]=1;for(int i=1;i<maxn;i++) 
         fac[i]=fac[i-1]*i%mod;//n!
     inv[1]=1;for(int i=2;i<maxn;i++) 
         inv[i]=inv[mod%i]*(mod-mod/i)%mod;//O(n)求1-n的逆元
     for(int i=2;i<maxn;i++) 
            inv[i]=inv[i-1]*inv[i]%mod;
    
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=4e6+100;
    const int mod=998244353;
    ll n,a[maxn],fac[maxn],inv[maxn];
    #define debug(x) cout<<#x<<':'<<x<<endl;
    int main(){
        
        fac[0]=1;for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;//n!
        inv[1]=1;for(int i=2;i<maxn;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;//O(n)求1-n的逆元
        for(int i=2;i<maxn;i++) inv[i]=inv[i-1]*inv[i]%mod;
        
        ll ans=0;
        scanf("%lld",&n);
        for(int i=1;i<=2*n;i++){
            scanf("%lld",&a[i]);
        }
        sort(a+1,a+2*n+1);
        for(int i=1;i<=n;i++) ans-=a[i];
        for(int i=n+1;i<=2*n;i++) ans+=a[i];
        ans=ans%mod*fac[2*n]%mod*inv[n]%mod*inv[n]%mod;
        printf("%lld",ans);
    }
    
  • 相关阅读:
    tips
    【十大算法实现之KNN】KNN算法实例(含测试数据和源码)
    智力趣题几则
    JAVA知多少
    R语言(入门小练习篇)
    文本分类,数据挖掘和机器学习
    推荐系统的循序进阶读物(从入门到精通)
    【贪心】PAT 1033. To Fill or Not to Fill (25)
    博弈故事一则——海盗分金币问题
    基于WordNet的英文同义词、近义词相似度评估及代码实现
  • 原文地址:https://www.cnblogs.com/zx0710/p/14391149.html
Copyright © 2011-2022 走看看