zoukankan      html  css  js  c++  java
  • Luogu6810 Convex Hull 凸包

    先写一下(Dirichlet) 前缀和

    就是求 (b_i=sumlimits_{j|i} a_j)

    (n le 2 imes 10^6)

    发现本质上 (a_i)(b_j) 有贡献是在唯一分解后 (a:c_kle b:c_k)

    可以筛完因数之后这样做:

    For(i,1,cnt)
    {
         for(reg int j=1;j*pri[i]*1ll<=n;++j) a[j*pri[i]]+=a[j];
    }
    

    具体的理解就是每次加的时候都是加上的这个因数上的前缀和

    (这种思想感觉挺妙的,不过感觉挺套路……)

    然后说这题的做法,一开始我把约数函数一拆,然后当场自闭,三张草稿纸瞬间交代

    保留着约数函数然后按照 简单的数学题 那个的做法可以得到:

    [sum_{T=1}^nsum_{g|T} d(g)mu(frac T g) sum_{i=1}^{lfloorfrac n T floor} sum_{j=1}^{lfloorfrac n T floor} d(iT)d(jT) ]

    (f=d * mu)

    (f(T)=sum_{g|T} f(g)mu(frac T g))

    其实可以用相关的组合式子给出 (f(x)=1) (直接唯一分解出来之后列式子就行了)

    然后要求的就是

    [sum_{T=1}^nsum_{i=1}^{lfloorfrac n T floor} sum_{j=1}^{lfloorfrac n T floor} d(iT)d(jT) ]

    (d) 直接筛,后面的部分用上面说的 (Dirichlet) 前缀和的转化(后缀和)

    时间复杂度降到了 (O(nlog log n)) (这里认为 (n,m) 同阶)

    #include<bits/stdc++.h>
    using namespace std;
    #define reg register
    #define For(i,a,b) for(reg int i=a;i<=b;++i)
    #define Down(i,a,b) for(reg int i=a;i>=b;--i)
    namespace yspm{
        inline int read()
        {
            int res=0,f=1; char k;
            while(!isdigit(k=getchar())) if(k=='-') f=-1;
            while(isdigit(k)) res=res*10+k-'0',k=getchar();
            return res*f;
        }
        const int N=5e7+10;
        int l[N],mod,pri[N/10],n,ans,d[N],cnt; 
        bool fl[N];
        inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
        inline int del(int x,int y){return x-y<0?x-y+mod:x-y;}
        inline int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
        signed main()
        {
            freopen("sum.in","r",stdin);
            freopen("sum.out","w",stdout);
            n=read(); mod=read(); 
            d[1]=1; 
            for(reg int i=2;i<=n;++i)
            {
                if(!fl[i]) pri[++cnt]=i,d[i]=2,l[i]=1; 
                for(reg int j=1;j<=cnt&&1ll*pri[j]*i<=n;++j)
                {
                    fl[i*pri[j]]=1;
                    if(i%pri[j]==0)
                    {
                        d[pri[j]*i]=d[i]/(l[i]+1)*(l[i]+2);
                        l[i*pri[j]]=l[i]+1;
                        break;
                    }else d[pri[j]*i]=d[i]*2,l[i*pri[j]]=1;
                }
            }
            for(reg int i=1;i<=cnt;++i) for(reg int j=n/pri[i];j>=1;--j) d[j]=add(d[j],d[j*pri[i]]);
            For(i,1,n) ans=add(ans,mul(d[i],d[i])); 
            printf("%d
    ",ans);
            return 0;
        }
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    linux下安装EJBCA 搭建私有CA服务器
    PHP 设计模式之观察者模式
    PHP 设计模式之三种工厂模式
    PHP 设计模式之单例模式
    解決 VMware Workstation 与 Device/Credential Guard 不相容,无法启动虚拟机的问题
    Mac 外接鼠标不好用?这个软件解决你的痛点
    PHP Trait 解决 PHP 单继承问题
    Wordpress 添加图片点击放大效果
    PHP 实现 WebSocket 协议
    Web 网页直接打开 Windows 软件
  • 原文地址:https://www.cnblogs.com/yspm/p/13681117.html
Copyright © 2011-2022 走看看