Detailed Screening prime Erichsen screening method (C ++ to achieve)

Description: Part of n and N are the same meaning, but is sensitive to the performance of specific and general form only, so that the reader may be interspersed with confusion, like him understanding.

A, defined prime number

Refers to an integer greater than 1, it can be divided by the number 1 and itself.

Second, the most important Erichsen screening conclusion:

N has a factor, then there is at least a factor of no more than half N \sqrt{N} .
For example, 100 is not judged to be a prime number, 100 = 10 X 10, as long as there is a factor of> 100 \sqrt{100} Bound to a factor other < 100 \sqrt{100} , So long as the presence or absence can be determined within a factor 10 100, to use this method of time complexity of O (n * √n).
So you may not really understand, read on.

Third, find [0, n] algorithm basic idea of ​​the range of all primes

  1. First 0,1 exclude:

  2. Create a list of consecutive integers from 2 to n, [2,3,4, ..., n];

  3. Initialization p = 2, since 2 is the smallest prime number;

  4. Enumerate all a multiple of p (2p, 3p, 4p, ...), marked as non-prime numbers (numbers together);

  5. Locate the tag and without a number p greater than one. If not, the end of the operation; if, given the values ​​of p, repeat steps 4;

  6. After the operation, all the remaining unmarked prime number is found.

This may be combined with the movable FIG appreciated below:
Here Insert Picture Description

Fourth, optimized application Erichsen screening ideas

We found [0, N] in the range of lot> N \sqrt{N} In fact, the number is [0, N \sqrt{N} ] Multiple of the number of the range. The> N \sqrt{N} And non [0, N \sqrt{N} , Is a multiple of the prime number] of the range of numbers.
For example: [0, 100] Many in the range of> 100 \sqrt{100} In fact, the number is [0, 100 \sqrt{100} The multiples] number range (12,14,16 is a multiple of 2, 3, ... it is a multiple 12,15,18). The> 100 \sqrt{100} And non [0, 100 \sqrt{100} (11,13,17 ...), multiples are prime numbers within a] number range.

So we make the following basic algorithms to optimize the title three ideas:
For Step 4, you can not begin to exclude from 2p, but directly from the p 2 p^2 start. In the beginning the reasons already mentioned, all less than p 2 p^2 the number of co-factors have less are excluded.

For Step 5, when the p 2 p^2 > n-time calculation is stopped.


Reference link:
"Using Eratosthenes screening method to quickly find prime numbers in the 2.1 billion"
"Eratosthenes prime number screening Solving Problems"


Int range when the range in:

#include<iostream>
#include<cstdio>
using namespace std;
    
const int maxn=5000000;
long prime[maxn];    // 存储一个个确定为质数的数
bool is_prime[maxn+1];    // 标记范围内所有数
int p = 0;
int sieve(int n)
{
 	p = 0;
	for(int i=0;i<=n;i++)
		is_prime[i]=true;       // 所有数先标记为true
    is_prime[0] = is_prime[1] = false;   // 把数字0,1标记为质数
    for(int i=2;i<=n;i++)
    {
       	if(is_prime[i])         // 如果这个数没有被标记为false
    	{
             prime[p++]=i;       // 用prime数组存起来这个数,既存起了质数,又用p表示了质数个数
             for(int j=i*i;j<=n;j+=i)   // 这里没有优化时的写法是for(int j=2*i; j<=n; j++)。
	    	//因为小于j(即i^2)内的合数都因为(根号j)(即i)内有更小的j的的因数而被排除
    							// 比如3^2 = 9,为什么不算2*3 = 6呢, 因为6<9,所以6因为3以内有更小的因数而直接被排除
    				is_prime[j]=false;
        }
    }
    return p;          // 返回质数个数
}
int main()
{
	int n;
	while(~scanf("%d",&n))
    {
    	printf("质数个数是: %d\n",sieve(n));
    	printf("质数有:\n");
    	for (int i = 0; i<p; i++)
    	{
    		printf("%d ", prime[i]);
    		printf("\n\n");
        }
   	}
    system("pause");
}	

When the range exceeds the int

static const int N = 1e7;
bool is_prime[N];   // 判断是否是素数
ll prime[N];       // 存储素数
ll sieve(ll num)
{
	int inx = 0;
	for (int i = 0; i<=N; i++)
		is_prime[i] = true;

	is_prime[0] = is_prime[1] = false;

	int MIN = (num > N) ? N : num;

	for (ll i = 2; i<=MIN; i++)
	{
		if (is_prime[i])
		{
			prime[inx++] = i;

			for (ll j = i*i; j<=num; j+=i)
				is_prime[j] = false;
		}
	}
	return inx;
}

int gcd(int inx)    // 此处由于传进来都是质数,所以直接相乘即为gcd
{
	int res = 1;
	for (int i = 0; i<inx-1; i++)
		res *= prime[i];
	return res;
}

void C3()
{
	ll num;     // 输入数
	int p;       // 最小公约数

	cin >> num;

	int inx = sieve(num);   // 筛选素数

	cout << gcd(inx) << endl;
}
Published 131 original articles · won praise 81 · views 60000 +

Guess you like

Origin blog.csdn.net/weixin_43469047/article/details/104752705