快速线性筛求素数问题

NO1

快速线性筛求素数问题(欧拉筛法)

 

特点:没有冗余,不会重复筛除一个数。 其时间复杂度几乎为O(n)。

原理:对于任意合数,必定可以有最小质因子乘以最大因子的分解方式。因此,对于每个合数,只要用最大因子筛一遍,枚举时只要枚举最小质因子即可。

 1 #include
 2 #define MAXN 1000010
 3 using namespace std;
 4 long prime[MAXN],number_prime;  //prime 为素数的集合,number_prime 为素数的个数
 5 bool vis[MAXN];  //vis 用于记录那些数不是素数
 6 inline void pd_prime(int number)  //number 是所求素数集合的上限
 7 {
 8     for(int i=2;i<=number;i++)
 9     {
10         if(!vis[i]) prime[number_prime++]=i;  //如果不在 非素数集合内 判定为素数--同时 number+1 (此时是number先赋值再+1,故prime序列从0开始)
11         for(int j=0;j)  //j要小于现在求出来的素数个数,并且下一步筛出的那个数(i*某已知素数要小于要求的上限)
12         {
13             vis[i*prime[j]]=true;  //能拆成 i*质数 为合数 筛出
14             if(!(i%prime[j])) break;  //见注解1 i%prime[j]==0
15         }
16     }
17 }
18 int main()
19 {
20     int n;
21     cin>>n;
22     pd_prime(n);
23     for(int i=0;iendl;
24     cout<"total number: "<<number_prime;
25     return 0;
26 }

注解1:只筛最小质因子

eg: 12=2*2*3

当 i=4 时,将 4*2 筛除---停止

......

当i=6时,将 6*2 筛除---6*3 筛除---停止

12的最小质因子为 2,只在 i=2 时筛了一遍

若 i=p1*p2*......*pn  设p2*......*pn 为q 则只筛除 x=i*p1 即 x= p1 * p1 *q。其余的合数 如: x2=p2*p1*q = (p2 * p2* ...... *pn) * p1; 在 i=(p2 * p2* ...... *pn) 时自然会筛除。

你可能感兴趣的:(快速线性筛求素数问题)