线性筛质数,线性求欧拉

前言

本篇前半部分讲线性筛质数,也叫欧拉筛,后半篇讲解线性求欧拉函数。

欧拉筛

我们有一种筛质数的办法,就是枚举每个质数,然后把这个质数的倍数都筛掉,这个做法比较简单,在这里不做过多介绍。欧拉筛就是在这个方法的基础上,使得每个合数只会被它最小的那个质因子筛掉,保证了复杂度是线性的

    memset(isprime,1,sizeof(isprime));
    isprime[1]=0;
    for (int i=2;i<=10000;i++){
        if (isprime[i]) prime[++primesize]=i;
        for (int j=1;j<=primesize&&i*prime[j]<=10000;j++){
            isprime[i*prime[j]]=0;
            if (i%prime[j]==0) break;
        }
    }

所有变量名都是字面意思。
若i%prime[j]==0,那么i*prime[j+1]也一定是prime[j]的倍数,一定被prime[j]筛过了,所以就可break了,这样就保证了每个合数只被自己的最小质因子筛一次。

线性筛欧拉

不知道欧拉函数计算公式的同学可以先看我上一篇博客,里面有详细的推导和证明。
还有两个前置知识
1:φ(p x)=p φ(x) 当 x mod p==0
我看了很多博客这里的证明都是略,所以我这里给出证明
φ(p x)=p x (1- 1a1 1 a 1 ) (1- 1a2 1 a 2 ) …… (1- 1an 1 a n )
其中 a1 a 1 an a n 均为p x的质因子
然后可以发现因为x是p的倍数,p是质数,所以x的质因子和p*x的质因子构成相同,所以结论就是对的了
2:φ(x p)=(p-1)*φ(x) 当 x mod p!=0
因为p是一个质数,而x不是p的倍数,所以x和p互质
根据φ是一个积性函数,φ(x p)=φ(p)*φ(x)
又因为p是质数,所以φ(p)=p-1,结论得证。
那么我们在线性筛的时候稍微改一下就可以了。

    memset(isprime,1,sizeof(isprime));
    isprime[1]=0;
    for (int i=2;i<=10000;i++){
        if (isprime[i]) prime[++primesize]=i,phi[i]=i-1;
        for (int j=1;j<=primesize&&i*prime[j]<=10000;j++){
            isprime[i*prime[j]]=0;
            if (i%prime[j]==0){
                phi[i*prime[j]]=prime[j]*phi[i];
                break;
            }
            else phi[i*prime[j]=(prime[j]-1)*phi[i];
        }
    }

还是保证了每个合数只会被算一次phi,复杂度就是对的了。
以上就是我个人对线性筛质数和线性求欧拉函数的理解,欢迎大家在评论里指正我的错误或提出意见,感激不尽。

你可能感兴趣的:(线性筛质数,线性求欧拉)