zoukankan      html  css  js  c++  java
  • 杜教筛学习笔记

    模板题

    洛谷P4213 【模板】杜教筛(Sum)

    前置知识

    常见积性函数的特性

    杜教筛

    杜教筛就是在非线性时间内求出积性函数前缀和的一种算法

    现在要求(S(n)=sumlimits_{i=1}^nf(i))的值

    其中f(i)是积性函数,n很大以至于O(n)并不能通过

    考虑一个积性函数(g(x)),求((f imes g)(x))的前缀和

    [ herefore sumlimits_{i=1}^n(f imes g)(i)\ =sumlimits_{i=1}^nsumlimits_{d|i}f(frac id)g(d)\ =sumlimits_{d=1}^ng(d)sumlimits_{i=1}^{lfloorfrac nd floor}f(i)\ =sumlimits_{d=1}^ng(d)S(lfloorfrac nd floor)\ ]

    因为g是积性函数,所以g(1)=1,所以S(n)=g(1)S(n)

    [ herefore S(n)=g(1)S(n)\ =sumlimits_{i=1}^ng(i)S(lfloorfrac ni floor)-sumlimits_{i=2}^ng(i)S(lfloorfrac ni floor)\ =sumlimits_{i=1}^n(f imes g)(i)-sumlimits_{i=1}^ng(i)S(lfloorfrac ni floor) ]

    其中(sumlimits_{i=1}^n(f imes g)(i))(f)(mu),(varphi),(varphi imes id)时,取(g)(I),则可以O(1)求出其值

    分别为(1),(frac{n(n+1)}{2})(frac{n(n+1)(2n+1)}6)

    其中(sumlimits_{i=1}^ng(i)S(lfloorfrac ni floor))可以用数论分块求出

    总时间复杂度(O(n^{frac 34}))

    如果先预处理出(S(1)到S(m)),则时间复杂度可以优化到(O(frac n{sqrt m})),证明略

    Code

    #include<bits/stdc++.h>
    #define N 5000000
    #define ll long long
    using namespace std;
    ll mu[N+varphiphi[N+5],prim[N+5],tot;
    bool apr[N+5];
    void pre(int n){
        mu[varphiphi[1]=1;
        for(int i=2;i<=n;i++){
            if(!apr[i])prim[++tot]=i,mu[i]=varphiphi[i]=i-1;
            for(int j=1;j<=tot&&prim[j]*i<=n;j++){
                apr[i*prim[j]]=1;
                if(i%prim[j]){
                    mu[i*prim[j]]=-mu[i];
                 varphiphi[i*prim[jvarphiphi[varphiphi[prim[j]];
                }else{
                    mu[i*prim[j]]=0;
                 varphiphi[i*prim[jvarphiphi[i]*prim[j];
                    break;
                }
            }
        }
        for(int i=2;i<=n;i++)mu[i]+=mu[i-varphiphi[ivarphiphi[i-1];
    }
    map<int,ll>mu_;
    ll SumMu(int n){
        if(n<=N)return mu[n];
        if(mu_[n])return mu_[n];
        ll re=0;
        for(int l=2,r=0;r<0x7fffffff&&l<=n;l=r+1){
            r=n/(n/l);
            re+=1ll*(r-l+1)*SumMu(n/l);
        }
        return mu_[n]=1ll-re;
    }
    map<int,varphiphi_;
    ll varphiPhi(int n){
        if(n<=N)retuvarphiphi[n];
        varphiphi_[n])retuvarphiphi_[n];
        ll re=0;
        for(int l=2,r=0;r<0x7fffffff&&l<=n;l=r+1){
            r=n/(n/l);
            re+=1ll*(r-l+1)*varphiPhi(n/l);
        }
        retuvarphiphi_[n]=1ll*n*(n+1ll)/2ll-re;
    }
    signed main(){
        pre(N);
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            printf("%lld %lld
    ",varphiPhi(n),SumMu(n));
        }
        return 0;
    }
    /*
    6
    1
    2
    8
    13
    30
    2333
    
    */
    
  • 相关阅读:
    【Rust】文件操作
    【Rust】转义字符
    【Rust】原始标识符
    【Rust】字节数组
    【Rust】文档测试
    【Rust】外部函数接口
    【Rust】不安全操作
    【Rust】单元测试
    【Rust】集成测试
    WPF之ComboBox 安静点
  • 原文地址:https://www.cnblogs.com/nlKOG/p/10843438.html
Copyright © 2011-2022 走看看