zoukankan      html  css  js  c++  java
  • 【Bzoj3944】杜教筛模板(狄利克雷卷积搞杜教筛)

      题目链接

      哇杜教筛超炫的

      有没有见过$O(n^frac{2}{3})$求欧拉函数前缀和的算法?没有吧?蛤蛤蛤

      首先我们来看狄利克雷卷积是什么

      首先我们把定义域是整数,陪域是复数的函数叫做数论函数。

      然后狄利克雷卷积是个函数和函数的运算。

      比如说有两个数论函数f,g

      那么它们的狄利克雷卷积就是f*g,记为h

      然后我们惊奇地发现$h(i)=sumlimits_{d|i}f(d)g(frac{i}{d})$

      而且狄利克雷卷积好像是个群,然后它就能满足交换律结合律分配律balaba

      那么这个玩意有什么卵用呢?

      (显然它很有卵用)

      我们再说一个数论函数叫单位元。

      e(1)=1 e(n)=0(n>1)

      然后我们发现任意函数f(x)有f*e=f

      然后就引出我们的杜教筛,这里计算莫比乌斯函数的前缀和

      设$S(n)=sumlimits_{i=1}^{n}miu(i)$

      然后我们随便代一个数论函数g,套上狄利克雷卷积

      $sumlimits_{i=1}^{n}(g*miu)(i)=sumlimits_{i=1}^{n}sumlimits_{d|i}miu(frac{i}{d})g(d)$

      $=sumlimits_{d=1}^{n}sumlimits_{d|i}miu(frac{i}{d})g(d)$

      $=sumlimits_{d=1}^{n}g(d)sumlimits_{i=1}^{frac{n}{d}}miu(i)$

      $=sumlimits_{d=1}^{n}g(d)S(frac{n}{d})$
      所以说$g(1)S(n)=sumlimits_{i=1}^{n}g(i)S(frac{n}{i})-sumlimits_{i=2}^{n}g(i)S(frac{n}{i})$

           $=sumlimits_{i=1}^{n}(g*miu)(i)-sumlimits_{i=2}^{n}g(i)S(frac{n}{i})$

      然后我们惊奇的发现,如果我们设g(x)=1

      因为1*miu=e(因为有个定理是$sumlimits_{d|n}miu(d)=$  n=1时1,n>1时0)

      那么这玩意就变成了$S(n)=1-sumlimits_{i=2}^{n}S(frac{n}{d})$

      然后这个玩意可以先用线性筛求出$n^frac{2}{3}$的前缀和,然后用这个表达式应用数论分块,递归搞搞就好了

      就问炫不炫

      

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<map>
    #define maxn 5000000
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int prime[maxn],tot;
    bool s[maxn];
    long long phi[maxn];
    long long miu[maxn];
    map<int,long long>_phi,_miu;
    
    long long calcmiu(long long n){
        if(n<maxn)    return miu[n];
        if(_miu.count(n)) return _miu[n];
        long long x=2,ans=1;
        while(x<=n){
            long long y=n/(n/x);
            ans-=calcmiu(n/x)*(y-x+1);
            x=y+1;
        }
        return _miu[n]=ans;
    }
    
    long long calcphi(long long n){
        if(n<maxn)    return phi[n];
        if(_phi.count(n)) return _phi[n];
        long long x=2,ans=n*(n+1)/2;
        while(x<=n){
            long long y=n/(n/x);
            ans-=calcphi(n/x)*(y-x+1);
            x=y+1;
        }
        return _phi[n]=ans;
    }
    
    int main(){
        int T=read();
        s[1]=1;miu[1]=1;phi[1]=1;miu[0]=0;phi[0]=0;
        for(int i=2;i<maxn;++i){
            if(!s[i]){
                s[i]=1;
                phi[i]=i-1;
                miu[i]=-1;
                prime[++tot]=i;
            }
            for(int j=1;j<=tot&&prime[j]*i<maxn;++j){
                s[prime[j]*i]=1;
                if(i%prime[j]){
                    miu[i*prime[j]]=-miu[i];
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
                }
                else{
                    phi[i*prime[j]]=phi[i]*prime[j];
                    miu[i*prime[j]]=0;
                    break;
                }
            }
        }
        for(int i=2;i<maxn;++i){
            phi[i]+=phi[i-1];
            miu[i]+=miu[i-1];
        }
        while(T--){
            long long n=read();
            printf("%lld %lld
    ",calcphi(n),calcmiu(n));
        }
        return 0;
    }
  • 相关阅读:
    leetcode643.滑动窗口例题
    BZOJ4195 离散化+并查集
    luogu线性表刷题
    2021-5-29 周报博客
    2021-5-28 日报博客
    2021-5-27 日报博客
    2021-5-26 日报博客
    2021-5-25 日报博客
    2021-5-24 日报博客
    梦断代码阅读笔记之二
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8227802.html
Copyright © 2011-2022 走看看