From linear sieve primes to Euler function (Eulerian function, linear sieve)

foreword

Konjac is preparing to make up maths recently TAT

Based on the linear sieve primes, the Euler function can be quickly obtained at the same time. So Konjac is going to start from here and sort out the ideas for realization.

Linear Sieve Primes and an Improved Writing Method

The method of linear sieving of prime numbers is to use known prime numbers to sieve out composite numbers containing this prime factor, which is very ingenious. Since it is not the focus of this article, just paste the code

#include<cstdio>
#include<cmath>
#define R register int
const int N=100000000,SQ=sqrt(N);
bool f[N];
int main(){
    R i,j;
    for(i=2;i<=SQ;++i){
        if(f[i])continue;
        for(j=i<<1;j<N;j+=i)f[j]=1;
    }
    /*for(i=2;i<N;++i)
        if(!f[i])printf("%d\n",i);*/
    return 0;
}

The complexity is not proven, but it is more approximate to linear.

Why is it an approximation? Because each composite number is sieved by its multiple prime factors, it is not strict.

So we have to find a way to make each composite number be filtered out only once. How to achieve it? We can make every composite number be filtered out only by its smallest prime factor. Compared with the above, this new and better writing method has undergone major changes. The code is as follows, which can be understood in combination with comments, and will not be discussed much.

#include<cstdio>
#include<cmath>
#define R register int
const int N=100000000,B=N>>1;
bool f[N];
int pr[B];
int main(){
    R i,j,p=0;
    for(i=2;i<=B;++i){
        if(f[i])
            for(j=1;j<=p&&i*pr[j]<N;++j){
                f[i*pr[j]]=1;
                if(!(i%pr[j]))break;//这一句话就是使得每个合数只被最小质因子筛掉的关键
//简要解释一下,如果pr[j]|i,那么i就有一个质因子pr[j]
//那么{i*pr[j+k],k∈N*}的最小质因子就是pr[j]而不是pr[j+k]了
            }
        else{
            pr[++p]=i;
            for(j=1;j<=p&&i*pr[j]<N;++j)
                f[i*pr[j]]=1;//i是质数,所以可以省掉上面那个判断,减小常数
        }
    }
    /*for(i=2;i<N;++i)
        if(!f[i])printf("%d\n",i);*/
    return 0;
}

The actual operation \(N=10^8\) is half faster than the above way of writing.

Euler function

Definition and Properties

Define the Euler function \(\phi(x)\) for a positive integer \(x\ ) , which is the number of integers that are relatively prime to \(x\) in \([1,x]\) .

Several basic contents (the following defines \(p\) as a prime number):

  1. \(\phi(1)=1\) , this is nothing to say, because it is originally defined that \(1\) and \(1 \) are relatively prime
  2. \(\phi(p)=p-1\) It is also obvious that it is derived from the definition of prime numbers
  3. If \(p|x\) then \(\phi(x*p)=\phi(x)*p\) else \(\phi(x*p)=\phi(x)*(p- 1)\) . If you prove it, please Baidu it, konjac can't qwq

In this case, is it possible to calculate the Euler function value of this composite number while sieving a prime number with a prime factor containing this number, just like the previous method of sieving prime numbers? It seems to be impossible, because the Euler function value of the quotient of the two numbers may not be calculated yet.

At this time, the following sieve method comes in handy again. Enumerate \(x\) and then enumerate prime numbers \(p\) , at this time \(\phi(x)\) and \(\phi(p)\) must be found, then \(\phi( x*p)\) of course also ask for it.

#include<cstdio>
#define R register
const int N=1000001;
int pr[N],phi[N];
bool f[N];
int main(){
    R int n,i,j,k,p=0;
    phi[1]=1;//内容1
    for(i=2;i<N;++i){
        if(!f[i])phi[pr[++p]=i]=i-1;//内容2
        for(j=1;j<=p&&(k=i*pr[j])<N;++j){
            f[k]=1;
            if(i%pr[j])//内容3
                phi[k]=phi[i]*(pr[j]-1);
            else{
                phi[k]=phi[i]*pr[j];
                break;
            }
        }
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324871227&siteId=291194637