Algorithm template: prime number bucket of number theory (including detailed explanation of Ehrlich sieve method and Euler linear sieve method) [Shen Qi]

Posted by stezz on Sat, 08 Jan 2022 13:17:40 +0100

preface

Just call me Shen Qi.
Recently, I have gained a lot from watching the video of AcWing algorithm basic course.
So I decided to open up the algorithm section and officially began to sort out the algorithm notes and clarify my ideas.

This time, we brought prime bucket. Hey, hey.
Each part will be matched with the corresponding exercise questions and posted. AcWing webmaster y always provides the corresponding algorithm template.
My task is to explain according to my understanding.
That's the same sentence.
Konjaku is so weak that it must be full of mistakes.
Welcome criticism and correction, and look forward to common growth!

Note:
Since y the general algorithm template is written in C + +,
Therefore, before reading this article, readers need to have a certain basic syntax knowledge of C + +. (such as the concept of bool type, etc.)

Prime number definition

A natural number greater than 1 that cannot be divided by other natural numbers except 1 and itself is called a prime number.

From this definition, we get the first method to judge prime numbers.

Trial division to judge prime numbers

Trial division is a method to judge prime numbers directly according to the definition of prime numbers.

bool is_prime(int x)
{
if (x < 2) //Prime numbers are greater than 1, that is, less than 2
return false;
for (int i = 2; i <= x ; i ++ )
if (x % i == 0)//Once there is a factor, it is not a prime number
return false;
return true;//All traverses again, no factor is found, that is, it is a prime number
}

Can it be further optimized?

Let i be the divisor of N, then i/n is also the divisor of n
as

n=12
i=2 => n/i=6 2 Is a divisor of 12, and 6 is also a divisor of 12.
i=3 => n/i=4 3 Is a divisor of 12, and 4 is also a divisor of 12.

Therefore, the divisors in n appear in pairs. We only need to enumerate the smaller one of a pair.
That is, the enumerator satisfies I < = n / I
arrangement

i<=n/i
i*i<=n
i<=sqrt(n)

So just enumerate to sqrt (n).

Scheme selection

1.i<n/i  [Degree of recommendation*****]
2.sqrt(n)[Not recommended. You need to call the function continuously math.h]
3.i*i<n  [Not recommended, int Type variable i Memory overflow risk]

So we got the first template.

Template

bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
return false;
return true;
}

Decomposition of prime factor by trial division

Decomposing the quality factor is also a common question,
It can also be solved by trial division.
According to the basic theorem of arithmetic, without considering the order of arrangement,
Each positive integer can be expressed in a unique way as the product of its prime factor.
For example, when a number 16 is decomposed, it first finds the prime factor of 2, and then it can be / 2 after 16 / 2, so it will produce a power on the prime factor of 2.
Not optimized version:
Find the divisible factor from 2~n and calculate the power.
So we can write code.

void divide(int x)
{
for (int i = 2; i <= x ; i ++ )
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
cout << endl;
}

Then we need to know another theorem:
N contains at most one prime number greater than the root n.
In fact, it is easy to prove that sqrt (n) * sqrt (n) = n. if both factors are greater than sqrt (n), the product is not n.
So we get the template of quality factor decomposition.

Template

void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )//Enumerate prime numbers less than root x first
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
if (x > 1) cout << x << ' ' << 1 << endl;//
cout << endl;
}

Ehrlich sieve method (simple sieve)

The data range in the question is the sixth power of 10, and the upper limit of some questions even reaches the eighth power of 10,
At this time, the simple division will definitely time out.
Therefore, a screening method is introduced below

Eratosthene sieve method, abbreviated as aeschner sieve or Elsevier sieve, is a simple algorithm for checking prime numbers proposed by the Greek mathematician eratosthene
-Baidu Encyclopedia

The time complexity of Ehrlich sieve method is O (n * LGN).
In short, it is to start traversal from the specified range, and delete the multiples of the traversed elements in the traversal process, and the rest is prime.
for example
When we sift through prime numbers, we find that,
After sifting out 2, the multiples 4, 6 and 8 of 2 must not be prime numbers;
After sifting out 3, the multiples 6, 9 and 12 of 3 must not be prime numbers.
In this way, there is no need to judge the multiples of 2 and 3.
prove:
Let p be prime.
If the element P is not deleted, it means that it is not a multiple of any number between 2~p-1, that is, there is no divisor of P between 2~p-1, so p is a prime number.

Template

void get_primes1(){
for(int i=2;i<=n;i++){
if(!st[i]){
primes[cnt++]=i;
for(int j=i;j<=n;j+=i) st[j]=true;//You can sift out all composite numbers with prime numbers;
}
}
}

Can it be faster

Euler sieve method (linear sieve)

Linear sieve method - O (n), when n = 1E7, it is basically twice as fast as Egyptian sieve method.
principle
In the traversal process, the minimum prime factor pj of the composite pj*i is found by enumerating the prime numbers stored in the prime array from small to large. Finally, all the composite numbers are deleted by the minimum prime factor pj.
prove
Core of the algorithm: x will only be screened by its minimum quality factor. Because it is screened only once, the time complexity is O (n), so it is called linear screening.

Template

void get_prime(int x) {
for(int i = 2; i <= x; i++) {
if(!st[i]) prime[cnt++] = i;
for(int j = 0; prime[j] <= x / i; j++) {
//Abbreviate prime[j] to p[j];
//For any composite number x, if pj is the minimum prime factor of X, it will be screened out when I < = x / P [J]
//Because i must enumerate to x/p[j] before enumerating to x, and when x/p[j] is not the factor of composite x,
//So x must be screened out when I < = x / P [J].
st[prime[j]*i] = true;
if(i % prime[j] == 0) break;
}
}
}

If i% p[j] = = 0, p[j] is determined as the i minimum prime factor, and p[j] is also determined as p[j] * i minimum prime factor,
At this time, it is necessary to exit the cycle, otherwise the number of next sieves is certainly not sieved by its minimum quality factor.
as
21 = 3 * 7 when the prime factor is 3, 21% 3 = = 0 should exit. If not, the next value prime is p[j]=5.
Namely
21 * 5 = 105 will be screened out by 5, but 105 = 3 * 5 * 7. The minimum quality factor should be 3 and should be screened out by 3, which is not in line with the idea of the algorithm.

If i% p[j]= 0, PJ is set to be less than all prime factors of i, so p[j] is also the minimum prime factor of p[j] * i.

If readers can't understand some details, they can try to recite the template first and master the template first.

End scattered flowers

ok, the above is all the explanations of the prime number family bucket. If there are omissions, errors or more understandable explanations, you are welcome to confide in me and I will supplement and improve it later. Because the author is so delicious, it really costs this guy a lot of energy to complete this blog, so I hope readers don't be stingy with their three consecutive high praise.

Topic exercise

To test whether knowledge is learned is, of course, to constantly brush questions. Below I give some questions related to prime numbers in the valley.
In the follow-up, if I have time to update the problem solution of this part of knowledge, I can study it together at that time.
P3912 prime number
P3383 [template] linear sieve prime
P1217 [USACO1.5] palindrome prime
P1075 [NOIP2012 popularization group] quality factor decomposition

Reference articles

reference
https://www.acwing.com/solution/