筛素数学习笔记

普通筛法:

暴力寻找..

for(int i = 2;i <= n;i ++)
	{
		bool flag = 0;
		for(int j = 2;j < i;j ++)
		{
			if(i%j == 0)
				flag = 1;
		}
		if(flag == 0)
			prime[++cnt] = i;
	}

埃式筛法:

for(int i = 1;i <= sqrt(n);i ++)
{
    if(!vis[i])
    for(int j = i*i;j <= n;j += i)
    {
        vis[j] = 1;
    }
}

线性筛:

线性筛法:
理解if(i%prime[ j ]==0)是关键。
原理:
1. 任何一个合数都可以表示成一个质数和一个数的乘积
2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:
A = x * y; (假设y是质数,x合数)
x = a * b; (假设a是质数,且a < x——>>a<y)
->  A = a * b * y = a * Z (Z = b * y)
即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积!!!!
这也是理解代码中 if(i%primes[j] == 0)break;的关键
例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查primes[1]=2即可,因为对于大于primes[1]的质数,像3,有:
8*3 = 2*4*3 = 12*2
也就是说24(8*3=24)并不需要在8时检查,在12时才检查

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool np[2333333];//不是素数
int prime[2333333];//是素数
int cnt = 0;
int main()
{
	int n;
	cin>>n;
	np[1] = 1;
	for(int i = 1;i <= n;i ++)
	{
		if(!np[i])
			prime[++cnt] = i;
		for(int j = 1;j <= cnt;j ++)
		{
			if(prime[j]*i > n)	break;
			np[prime[j]*i] = 1;
			if(i%prime[j] == 0)	break;
		}
	}
	for(int i = 1;i <= cnt;i ++)
	{
		cout<<prime[i]<<endl;
	}
	return 0;
}

 

上一篇
下一篇