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
  • 相关阅读:
    NRF24L01 使用小结/自动应答/通道地址
    nRF24L01单片机通信的总结--看了就会用了
    彻底搞懂状态机(一段式、两段式、三段式)
    面向硬件的设计思维--时钟是电路的实际控制者
    组合逻辑电路-----竞争与冒险现象
    Win7、Win8、Win10系统USB-Blaster驱动程序无法安装的解决办法
    从DTFT到DFS,从DFS到DFT,从DFT到FFT,从一维到二维
    离散傅里叶级数DFS几个主要的特性
    离散傅里叶级数DFS
    Ubuntu12.10下Python(cx_Oracle)访问Oracle解决方案
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5821862.html
Copyright © 2011-2022 走看看