码迷,mamicode.com
首页 > 其他好文 > 详细

【Bzoj3944】杜教筛模板(狄利克雷卷积搞杜教筛)

时间:2018-01-07 16:06:27      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:lin   through   一个   就是   cstring   cal   ace   http   limit   

  题目链接

  哇杜教筛超炫的

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

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

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

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

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

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

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

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

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

  (显然它很有卵用)

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

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

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

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

  设$S(n)=\sum\limits_{i=1}{n}miu(i)$

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

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

  $=\sum\limits_{d=1}^{n}\sum\limits_{d|i}miu(\frac{i}{d})g(d)$

  $=\sum\limits_{d=1}^{n}g(d)\sum\limits_{i=1}^{\frac{n}{d}}miu(i)$

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

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

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

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

  那么这玩意就变成了$S(n)=1-\sum\limits_{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\n",calcphi(n),calcmiu(n));
    }
    return 0;
}

 

【Bzoj3944】杜教筛模板(狄利克雷卷积搞杜教筛)

标签:lin   through   一个   就是   cstring   cal   ace   http   limit   

原文地址:https://www.cnblogs.com/cellular-automaton/p/8227802.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!