zoukankan      html  css  js  c++  java
  • 51nod 1575 Gcd and Lcm

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1575

    万年巨坑终于填掉了……

    首先是煞笔西瓜的做题历程O_O。

    原题要求$sum_{i=1}^nsum_{j=1}^isum_{k=1}^i [(i,j),(i,k)]$

    那么先推一波式子吧

    balabala

    我也忘记自己是怎么推的了(雾

    总之最后推出来是这样的

    $ ans=sum_{i=1}^{n} f(leftlfloorfrac{n}{i} ight floor)*g(i) $

    其中 $ f(x)=sum_{i=1}^{x} μ(i)*i^2*frac{frac{x}{i}(frac{x}{i}+1)}{2} $  ,$ g(x)=[sum_{d|x} frac{x}{d}*φ(d)]^2 $

    然后接下来的问题就是怎么求f(x)的值和g(x)的前缀和了,求出来就能分段计算辣。

    嗯……

    想想怎么求……

    $ μ(i)*i^2 $ 可以用杜教筛直接求嘛,然后f(x)就可以O(3/4)分段求,可是在总式里面再跑一次分段的话复杂度会……诶,不管了,先写。

    g(x)的前缀和可以洲阁筛求,嗯,码码码……(这么复杂的题怎么才7级?

    啊,T了,意料之中……

    改改改

    跑得越来越快了……

    诶,极限数据要跑两秒多,可是10组数据的话还是要10多秒

    改不动,弃坑……

    (51nod群上问了下,夹克老爷说他不会。

    问问YJQ

    他说$ sum_{j=1}^isum_{k=1}^i [(i,j),(i,k)] $ 这东西是个积性函数。

    所以直接用洲阁筛对这个东西求前缀和就好了(掀桌……

    也就是说,看到题目,你开始推式子,你就输辣。

    具体来说,对于一个质数$ p $,当 $ i=p^k $ 时,$ sum_{j=1}^isum_{k=1}^i [(i,j),(i,k)] =(2k+1)*(p^{2k}-p^{2k-1})+p^{k-1} $

    优越写法才2.8k,第一种方法直接上5k……

    代码不贴辣。

    upd at 2017.4.26好像这题烂大街了,我来发个洲阁筛模板吧

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ui unsigned int
    #define ull unsigned long long
    #define MN 100001
    #define SQ 64000
    using namespace std;
    ui read_p,read_ca;
    inline ui read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    const ui HA=1e6+7;
    ui T,n,MMH,p[MN/10],_p[MN/10],num=0,TTT,O,Num,f[SQ],_S[SQ],G_2[SQ],G_1[SQ],G_0[SQ],_T[SQ],P_P[MN/10],_G_2[MN/10],_G_1[MN/10],_O[SQ],_Num,_l[HA],NNN=0,LL;bool bo[MN];
    ui gcd(ui x,ui y){return y?gcd(y,x%y):x;}
    ui _b_y[HA],_b_z[HA],_b_ne[HA];
    inline void _in(ui x,ui y,ui z){_b_y[++_Num]=y;_b_z[_Num]=z;_b_ne[_Num]=_l[x];_l[x]=_Num;}
    inline ui Q_2(ui x){if (x%6==1)return (ull)(x+x+1)*(x+1)/6*x;else if (x%6==4) return (ull)(x+x+1)*x/6*(x+1);else return (ull)x*(x+1)/6*(x+x+1);}
    inline ui Q_1(ui x){return (ull)x*(x+1)>>1;}
    inline ui sqr(ui x){return x*x;}
    inline ui min(ui a,ui b){return a<b?a:b;}
    inline ui find(ui x){
        if (x<HA) return _b_z[_l[x]];
        register ui i;
        for (i=_l[x%HA];i;i=_b_ne[i]) if (_b_y[i]==x) return _b_z[i];
        return 0;
    }
    inline ui Mmh(ui n){
        register ui i,j,c;ui o=sqrt(n)+1e-9,MMH=0,k=0,R,Ls,Rs,P,SS=0;ull x,Q,O_O;
        while (p[LL+1]<=o&&LL<num) LL++;
        for (i=1;i<=n;i=j+1) j=n/(c=n/i),_S[++k]=c,_in(c%HA,c,k),_T[k]=f[k]=0,G_2[k]=Q_2(c),G_1[k]=Q_1(c),G_0[k]=c;
        for (i=k,j=0;i;_O[i--]=j) while (_S[i]>=p[j+1]) j++;
        for (f[i=1]=1,P=Ls=Rs=k;i<=LL;i++){
            if (i==1) while (_S[P]<_p[i]&&P) P--;else P=Rs;
            while (_S[Rs]<_p[i+1]&&Rs) SS+=f[Rs--];
            while (_S[Ls]<p[i+1]&&Ls) SS-=f[Ls--];
            if (i!=LL) MMH+=SS*P_P[i+1];
            for (j=P;j;j--)
            if (f[j]){
                for (x=p[i],Q=1,c=1;x<=_S[j];x*=p[i],Q*=p[i],c++){
                    R=find(_S[j]/x);
                    f[R]+=(O_O=f[j]*((2*c+1)*(p[i]-1)*sqr(Q)*p[i]+Q));if (Ls>=R&&R>Rs) SS+=O_O;
                    if (i!=LL) if (_S[R]>=p[i+1]&&_S[R]<_p[i+1]) MMH+=O_O*P_P[i+1];
                }
            }
            for (j=1;j<=P;j++)
            if (_S[j]>=p[i]) c=min(i-1,_O[R=find(_S[j]/p[i])]),
            G_2[j]-=_p[i]*(G_2[R]-(_G_2[c]-_G_2[_T[R]]))+(_G_2[i-1]-_G_2[_T[j]]),
            G_1[j]-=p[i]*(G_1[R]-(_G_1[c]-_G_1[_T[R]]))+(_G_1[i-1]-_G_1[_T[j]]),
            G_0[j]-=(G_0[R]-(c-_T[R]))+(i-1-_T[j]),_T[j]=i;
        }
        for (j=1;j<=k;j++) c=min(LL,_O[j]),G_2[j]-=_G_2[c]-_G_2[_T[j]],G_1[j]-=_G_1[c]-_G_1[_T[j]],G_0[j]-=c-_T[j];
        for (i=1;i<=k;i++) MMH+=f[i]*((G_2[i]-G_1[i])*3+G_0[i]),_l[_S[k]%HA]=0;
        return _Num=0,MMH;
    }
    int main(){
        register ui i,j;
        for (i=2;i<MN;i++){
            if (!bo[i]) p[++num]=i,_p[num]=p[num]*p[num],_G_2[num]=_G_2[num-1]+_p[num],_G_1[num]=_G_1[num-1]+p[num],P_P[num]=3*p[num]*(p[num]-1)+1;
            for (j=1;j<=num&&(O=i*p[j])<MN;j++){
                bo[O]=1;
                if (!i%p[j]) break;
            }
        }
        T=read();while(T--){
            n=read();
            printf("%u
    ",Mmh(n));
        }
    }
    View Code
  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5821862.html
Copyright © 2011-2022 走看看