Today, we have gained a lot. We have created a fast O (n) Complexity to calculate all prime numbers in the range of 1-1000,000.
Note: This method is indeed self-developed. If you want to convert it, please enter this article. Otherwise, I will be very upset.
Idea: first define an array of isprime [1000001] and initialize it to 0. isprime [I] = 0 indicates that I is not sure whether it is a prime number, isprime [I] = 1 indicates that I must not be a prime number.
For a number, it must be obtained by multiplying some prime numbers. If we obtain an X as a prime number, we can use X to remove the number that is greater than X.
However, this is not enough, because X traverses from 2 to 1000,000, and X multiples also need to traverse from X to 1000,000.
At this time, we can find that a connection can be optimized (when we talk about the word "determining" below, it means determining whether it is a prime number) (obviously, when x traverses an isprime [x] = 0, it means that X is not regarded as a combination by a prime number smaller than X, and X is certainly not a factor greater than X, so X must be a prime number)
(1), X multiple x * Y. When determining x * y, y does not have to be smaller than X, because if y is smaller than X, then x * y must have been determined before. How to explain: in two cases, if y is a prime number, x * Y has been determined by Y. If y is not a prime number, then x * y must have been determined by the Y Factor. At this time, x * y does not need to be determined.
(2), x y, y must not have been determined as isprime [y] = 1, that is, y must not be a prime number, that is, Y is a Union number, at this time, the factor of Y must be less than or equal to X (note that there is a case of equal, and the case explained later must be specially handled), because y has been determined, this factor must also be a factor of x * y, so x * Y has been determined not to be a prime number.
For optimization, we can store all 2-1000,000 in a two-way linked list and use where [I] to represent the Node Address in the I linked list, when I is determined to be not a prime number, I can be deleted from the linked list. With where, I can be deleted without traversal.
Each time a prime number is obtained, the traversal table is used to obtain the number of keys that are determined to be a combination. After deleting the number of climblient linked list, the traversal jumps out until the number is greater than 1000,000. Then, each traversal of a node deletes a node, the complexity of this algorithm can be understood as the number of nodes that are traversed by a 1000,000-length linked list in O (n) operations. The total complexity is O (n ).
Note that we cannot delete a number z from the list if it is determined by the prime number X to the sum of numbers Z. Why? Because all the factors of Z are x, z is deleted, then z * x cannot be determined. In this case, we can delete Z after Z is used, and those cannot be reused, that is, if the value of z * X is greater than 1000,000, it is directly deleted from the linked list.
Note that int overflow exists, so we can define the value of the storage multiplication of an int64 variable.
Template code: the annotation part is the complexity of the algorithm I tested. For prime numbers less than 1000,000, only or steps are used.
# Include <stdio. h>
# Include <string. h>
# Deprecision Max 1000000
Typedef _ int64 ll;
Struct list
{
List * last;
Int value;
List * next;
};
Bool isprime [Max + 1];
List * Where [Max + 1];
Int isresult [Max + 1];
Int Init ()
{
Int I;
Ll temp, temp1;
List * P;
List * P1;
List * Q1;
List * head;
// Int step = 0; // number of steps used for testing
Memset (isprime, 0, sizeof (isprime ));
For (I = 2; I <= max; I ++)
{
P = new list;
Where [I] = P;
If (I = 2)
{
P-> last = NULL;
P-> value = I;
P-> next = NULL;
Head = P;
}
Else
{
P-> last = where [I-1];
Where [I-1]-> next = P;
P-> value = I;
P-> next = NULL;
}
}
For (I = 2; I <= max; I ++)
{
If (isprime [I])
Continue;
Else
{
For (P = head; P! = NULL; P = p-> next)
{
// Step ++; // number of steps used for testing
Temp = I * (LL) (p-> value );
If (isprime [p-> value] & where [p-> value]! = NULL)
{
Temp1 = p-> value;
P1 = where [temp1]-> last;
Q1 = where [temp1]-> next;
P1-> next = Q1;
If (Q1! = NULL)
Q1-> last = p1;
Delete where [temp1];
Where [temp1] = NULL;
P = p1;
}
If (temp> MAX)
Break;
If (! Isprime [temp])
{
Isprime [temp] = 1;
If (temp * I> MAX)
{
P1 = where [temp]-> last;
Q1 = where [temp]-> next;
Delete where [temp];
Where [temp] = NULL;
P1-> next = Q1;
If (Q1! = NULL)
Q1-> last = p1;
}
}
}
}
}
// Printf ("% d \ n", step); // number of steps used for testing
}