筛法

· · 个人记录

概述

埃氏筛

欧拉筛(线性筛)

bool np[maxv];
int p[maxv],ptot;
il void init(){
    np[1]=1; int res;
    For(i,2,usev){
        if(!np[i]) p[++ptot]=i;
        for(int j=1;j<=ptot && i*(ll)p[j]<=usev;++j){
            res=i*p[j],np[res]=1;
            if(!(i%p[j])) break;
        }
    }
    return;
}

杜教筛

\begin{aligned} H(n) & =\sum\limits_{i=1}^n \sum\limits_{d\mid i} f(\frac{i}{d})g(d) \\ & =\sum\limits_{d=1}^n g(d) \sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor} f(j) \\ & =\sum\limits_{d=1}^n g(d)F(\lfloor\frac{n}{d}\rfloor) \\ & =g(1)F(n)+\sum\limits_{d=2}^n g(d)F(\lfloor\frac{n}{d}\rfloor) \end{aligned} F(n)=H(n)-\sum\limits_{d=2}^n g(d)F(\lfloor\frac{n}{d}\rfloor)

\mu

\varphi

\begin{aligned} \sum\limits_{i=1}^n \varphi(i) & =\sum\limits_{i=1}^n \sum\limits_{j=1}^i [gcd(i,j)=1] \\ & =\sum\limits_{i=1}^n \sum\limits_{j=1}^i \sum\limits_{d\mid i \And d\mid j} \mu(d) \\ & =\sum\limits_{d=1}^n \mu(d) \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} i \\ & =\sum\limits_{d=1}^n \mu(d) \dfrac{\lfloor\frac{n}{d}\rfloor(\lfloor\frac{n}{d}\rfloor+1)}{2} \end{aligned}
namespace du{
    bool np[maxn23];
    int p[maxn23],ptot;
    int mu[maxn23],smu[maxn23];
    il void init(){
        np[1]=1,mu[1]=smu[1]=1; int res;
        For(i,2,usen23){
            if(!np[i]) p[++ptot]=i,mu[i]=-1;
            smu[i]=smu[i-1]+mu[i];
            for(int j=1;j<=ptot && i*(ll)p[j]<=usen23ll;++j){
                res=i*p[j],np[res]=1;
                if(i%p[j]) mu[res]=-mu[i];
                else break;
            }
        }
        return;
    }

    struct my_hash{
        static ull splitmix64(ull x){
            x+=0x9e3779b97f4a7c15;
            x=(x^(x>>30))*0xbf58476d1ce4e5b9;
            x=(x^(x>>27))*0x94d049bb133111eb;
            return x^(x>>31);
        }

        size_t operator()(ull x) const {
            static const ull FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
            return splitmix64(x + FIXED_RANDOM);
        }
    };
    u_map<int,int,my_hash> smu2;
    il int getmu(int n){
        if(n<=usen23) return smu[n];
        if(smu2.find(n)!=smu2.end()) return smu2[n];
        int ret=1,res;
        for(int l=2,r;;l=r+1){
            res=n/l,r=n/res;
            ret=ret-(r-l+1)*getmu(res);
            if(r==n) break;
        }
        return smu2[n]=ret;
    }

    il ll getphi(int n){
        static ll ret; ret=0;
        static int res;
        for(int l=1,r;;l=r+1){
            res=n/l,r=n/res;
            ret=ret+(getmu(r)-getmu(l-1))*(res*(res+1ll)/2);
            if(r==n) break;
        }
        return ret;
    }
}

id\mu

(f\ast g)(n)=\sum\limits_{d\mid n}d\mu(d)g(\frac{n}{d}) (id\ast id)(n)=\sum\limits_{d\mid n} d\frac{n}{d}=nd(n) \begin{aligned} (f\ast g)(n) & =\sum\limits_{d\mid n} d\mu(d)\frac{n}{d} \\ & =n\sum\limits_{d\mid n} \mu(d) \\ & =n(\mu \ast I)(n) \\ & =n\epsilon(n) \\ & =\epsilon(n) \end{aligned}

id\varphi

\begin{aligned} (f\ast g)(n) & =n\sum\limits_{d\mid n} \varphi(d) \\ & =n(\varphi\ast I)(n) \\ & =nid(n) \\ & =id_2(n) \end{aligned}

P3768 简单的数学题

\begin{aligned} \sum\limits_{i=1}^n \sum\limits_{j=1}^n ij(i,j) & =\sum\limits_{d=1}^n d \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} i\times d \sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor} j\times d\times [(i,j)=1] \\ & =\sum\limits_{d=1}^n d^3 \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} i \sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor} j \times \epsilon((i,j)) \\ & =\sum\limits_{d=1}^n d^3 \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} i \sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor} j \sum\limits_{t\mid i\And t\mid j} \mu(t) \\ & =\sum\limits_{d=1}^n d^3 \sum\limits_{t=1}^{\lfloor\frac{n}{d}\rfloor} \mu(t) \sum\limits_{i=1}^{\lfloor\frac{n}{td}\rfloor} i\times t \sum\limits_{j=1}^{\lfloor\frac{n}{td}\rfloor} j\times t \\ & =\sum\limits_{d=1}^n d^3 \sum\limits_{t=1}^{\lfloor\frac{n}{d}\rfloor} t^2\mu(t) \sum\limits_{i=1}^{\lfloor\frac{n}{td}\rfloor} i \sum\limits_{j=1}^{\lfloor\frac{n}{td}\rfloor} j \\ & =\sum\limits_{d=1}^n d^3 \sum\limits_{t=1}^{\lfloor\frac{n}{d}\rfloor} t^2\mu(t) \frac{\lfloor\frac{n}{td}\rfloor^2(\lfloor\frac{n}{td}\rfloor+1)^2}{4} \\ & =\sum\limits_{td=1}^n td^2\frac{\lfloor\frac{n}{td}\rfloor^2(\lfloor\frac{n}{td}\rfloor+1)^2}{4} \sum\limits_{d\mid td} d\mu(\frac{td}{d}) \\ & =\sum\limits_{td=1}^n td^2 \varphi(td)\frac{\lfloor\frac{n}{td}\rfloor^2(\lfloor\frac{n}{td}\rfloor+1)^2}{4} \end{aligned} \begin{aligned} \sum\limits_{i=1}^n \sum\limits_{j=1}^n ij(i,j) & =\sum\limits_{i=1}^n \sum\limits_{j=1}^n ij\times id((i,j)) \\ & =\sum\limits_{i=1}^n \sum\limits_{j=1}^n ij \sum\limits_{d\mid i\And d\mid j} \varphi(d) \\ & =\sum\limits_{d=1}^n d^2\varphi(d) \sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor} i \sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor} j \\ & =\sum\limits_{d=1}^n d^2\varphi(d)\frac{\lfloor\frac{n}{d}\rfloor^2(\lfloor\frac{n}{d}\rfloor+1)^2}{4} \end{aligned} (f\ast g)(n)=\sum\limits_{d\mid n} d^2\varphi(d)(\frac{n}{d})^2=n^2\sum\limits_{d\mid n}\varphi(d)=n^3=id_3(n) \begin{aligned} ID^2(n) & =\sum\limits_{i=1}^n \sum\limits_{d\mid i}f(\frac{n}{i})id_2(i) \\ & =\sum\limits_{d=1}^n id_2(d)F(\lfloor\frac{n}{d}\rfloor) \\ & =F(n)+\sum\limits_{d=2}^n id_2(d)F(\lfloor\frac{n}{d}\rfloor) \end{aligned} F(n)=(\frac{n(n+1)}{2})^2-\sum\limits_{d=2}^n id_2(d)F(\lfloor\frac{n}{d}\rfloor)

Powerful Number 筛

\begin{aligned} F(n) & =\sum\limits_{i=1}^n \sum\limits_{d\mid i} g(d)h(\frac{n}{d}) \\ & =\sum\limits_{d=1}^n h(d)G(\lfloor\frac{n}{d}\rfloor) \end{aligned}

Powerful Number

F(n)=\sum\limits_{i\in PN\And i\leqslant n} h(i)G(\lfloor\frac{n}{i}\rfloor)
namespace du{
    //f=iphi(i),g=id,h=id_2
    const int maxn23=4641593,maxpn23=325167;
    const ll usen23=4641590;
    ll n23;
    bool np[maxn23];
    ll p[maxpn23]; int ptot;
    ll f[maxn23],sf[maxn23];
    il void init(){
        n23=ceil(pow(n,2/(long double)3));
        np[1]=1,f[1]=sf[1]=1; ll res;
        for(ll i=2;i<=n23;++i){
            if(!np[i]) p[++ptot]=i,f[i]=i*(i-1)%mod;
            sf[i]=addr(sf[i-1],f[i]);//printf("phi[%lld]:%lld f[%lld]:%lld sf[%lld]:%lld\n",i,phi[i],i,f[i],i,sf[i]);
            for(int j=1;i*p[j]<=n23 && j<=ptot;++j){
                res=i*p[j],np[res]=1;
                if(i%p[j]) f[res]=f[i]*p[j]%mod*(p[j]-1)%mod;
                else{
                    f[res]=f[i]*p[j]%mod*p[j]%mod;
                    break;
                }
            }
        }
        return;
    }

    il ll getid(ll nnow){nnow%=mod; return nnow*(nnow+1)%mod*inv[2]%mod;}
    il ll getid2(ll nnow){nnow%=mod; return nnow*(nnow+1)%mod*(2*nnow+1)%mod*inv[6]%mod;}

    struct my_hash{
        static ull splitmix64(ull x){
            x+=0x9e3779b97f4a7c15;
            x=(x^(x>>30))*0xbf58476d1ce4e5b9;
            x=(x^(x>>27))*0x94d049bb133111eb;
            return x^(x>>31);
        }

        size_t operator()(ull x) const {
            static const ull FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
            return splitmix64(x + FIXED_RANDOM);
        }
    };
    u_map<ll,ll,my_hash> sf2;
    il ll getf(ll nnow){
        if(nnow<=n23) return sf[nnow];
        if(sf2.find(nnow)!=sf2.end()) return sf2[nnow];
        ll ret=getid2(nnow); static ll res;
        for(ll l=2,r;;l=r+1){
            res=nnow/l,r=nnow/res;
            minu(ret,minur(getid(r),getid(l-1))*getf(res)%mod);
            if(r==nnow) break;
        }
        return sf2[nnow]=ret;
    }
}

namespace pn{
    //f(p^k)=p^k(p^k-1),g=idphi,h=? 这里 g 是 du::f
    const int maxpsq=9597;
    ll nsq; int uptot;
    vector<ll> h[maxpsq];//h[i][j] 表示 h(p[i]^j) 的值
    il void init(){//计算 h(p^k)。
        //注意到至少 h(p^2) 处才有值,故只需要考虑 sqrt(n) 以内的质数 
        nsq=ceil(sqrt(n)); if(n==1) return;//这是因为 n=1 时 p[1]=0,但我不想在循环里加判断 
        ll powp[36]={1}; int top=0;//2^35>10^10,足够了 
        for(int i=1;du::p[i]<=nsq;++i){
            while(powp[top]*du::p[i]<=n) ++top,powp[top]=powp[top-1]*du::p[i];
            h[i].resize(top+1),h[i][0]=1,h[i][1]=0;
            For(k,2,top){
                powp[k]%=mod;
                h[i][k]=powp[k]*(powp[k]-1)%mod;
                For(j,1,k) minu(h[i][k],(powp[j]*minur(powp[j],powp[j-1])%mod)*h[i][k-j]%mod);
            }
            top=0,uptot=i;
        }
        return;
    }

    ll nnow,lim[maxpsq],sum;
    il void dfs(int now,ll vn,ll hn){//考虑到第几个质数,当前的值是多少,当前的 h 是多少 
        if(now>uptot || vn*du::p[now]>=lim[now]){//计算贡献。这个剪枝非常重要。 
            sum=(sum+hn*du::getf(nnow/vn))%mod;
            return;
        }
        dfs(now+1,vn,hn);//k 为 0
        int k=2;
        for(ll res=vn*du::p[now];res<lim[now];res=res*du::p[now],++k) dfs(now+1,res*du::p[now],hn*h[now][k]%mod);
        return; 
    }

    il ll getf(ll nnowin){
        nnow=nnowin;
        For(i,1,uptot) lim[i]=nnow/du::p[i]+1;//这是一个防止 10^10 相乘爆 ll 的 trick,记 v*p=x,则 x*p<=nnow->x<=nnow/p->x<floor(nnow/p)+1 
        sum=0;
        dfs(1,1,1);
        return sum;
    }
}

P5325 【模板】Min_25 筛

\begin{aligned} f(p^k) & =(g\ast h)(p^k) \\ & =\sum\limits_{i=0}^k g(p^{k-i})h(p^i) \\ & =h(p^k)+\sum\limits_{i=1}^k p^{k-i}\varphi(p^{k-i})h(p^i) \\ & =h(p^k)+\sum\limits_{i=1}^k p^{k-i}(p-1)p^{k-i-1}h(p^i) \\ & =h(p^k)+\sum\limits_{i=1}^k p^{2k-2i-1}(p-1)h(p^i) \end{aligned}

HDU7186 Jo loves counting