欧拉筛法与积性函数

来源:互联网 发布:酷听说软件问题 编辑:程序博客网 时间:2024/05/16 07:05

欧拉筛法

普通的筛法,即Eratosthenes筛法,复杂度为O(nloglogn),当范围大时,就扛不住了,需要利用欧拉筛法,也称线性筛法,下面还会介绍利用欧拉筛法的优美性质来求积性函数。
先给出欧拉筛法的代码:

for(int i=2;i<=n;i++){    if(vis[i])prime[++prime[0]]=i;    for(int j=1;j<=prime[0]&&prime[j]*i<=n;j++){        vis[i*prime[j]]=0;        if(!(i%prime[j]))break;    }}

欧拉筛法的思想是:
1.如果这个数是质数,那么就将它与之前的质数的乘积挖掉
2.如果这个数是合数,那么就将它与从2到它最小的质因子之间的质数的乘积分别挖掉
考虑一个数n=p1k1p2k2......,对于大于p1的质数j,令k=n/p1nj=pkj,所以这样的数可以通过p1来筛到,没有必要再去枚举。并且,这样的话,n只有可能会被p1k11p2k2......筛到,所以每个数只会被筛一次。所以,它的复杂度为O(n)

用欧拉筛法求欧拉函数

先来回顾一下欧拉函数有什么性质:
1.它是一个积性函数,即当(i,j)=1,ϕ(ij)=ϕ(i)ϕ(j)
2.对于任意的质数p,ϕ(p)=p1
3.对于任意的质数p,ϕ(pk)=(p1)pk1
所以我们分两种情况讨论:
1.n%p>0
显然,ϕ(np)=ϕ(n)(p1)
2.n%p=0
由于n,p不互质,所以不能直接用积性推了。假设n中有k个p这个质因子,ϕ(np)=ϕ(n/pk)ϕ(pk+1)=ϕ(n/pk)pk(p1)=ϕ(n/pk)ϕ(pk)p=ϕ(n)p
代码如下:

for(int i=2;i<=n;i++){    if(vis[i])prime[++prime[0]]=i,phi[i]=i-1;    for(int j=1;j<=prime[0]&&prime[j]*i<=n;j++){        vis[i*prime[j]]=0;        if(!(i%prime[j])){            phi[i*prime[j]]=phi[i]*prime[j];            break;        }        phi[i*prime[j]]=phi[i]*(prime[j]-1);    }}
原创粉丝点击