对筛质数三种方法的理解[普通筛,诶氏筛,线性筛]
//primes数组用来存放质数
int primes[N], cnt;
//i如果是质数则false,否则为true
bool st[N];
1.普通筛法 O(nlogn)
void get_primes(){
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[cnt++] = i; //把素数存起来
for(int j = i; j <= n; j += i)//不管是合数还是质数,都用来筛掉后面它的倍数
st[j] = true;
}
}
2.诶氏筛法 O(nloglogn)
void get_primes(){
for(int i = 2; i <= n; i ++)
{
if(!st[i]){
primes[cnt++] = i; //把素数存起来
for(int j = i; j <= n; j += i)//仅用质数就可筛掉所有合数
st[j] = true;
}
}
}
3.线性筛法 O(n)
void get_primes(){
for(int i = 2; i <= n; i ++)
{
if(!st[i]) primes[cnt++] = i;
for(int j = 0; primes[j] <= n/i; j ++)
{
st[primes[j]*i] = true; //用最小质因子筛合数(已经挑出来的质因子的i倍)
if(i % primes[j] == 0) break; // 此时primes[j]是i的i的最小质因子
}
}
}
if(i % primes[j] == 0) break;
对于👆的理解:
对于一个数c=ab(b为c的最小质因数),当通过该算法的循环循环至cb时,易得此时c%b==0,如果此时继续循环至b后面的一个素数d,则有:cd=abd=(ad)b,因为d>b,所以ad>c。当循环从c继续查找到ad时我们发现当ad再次与素数b想乘时,就又对c*d进行了一次操作,出现了冗余,所以在if(n%prime[j]==0)成立时要将该层循环break掉;
举个例子,对于一个数9,92=18将18标记为合数,循环继续;93=27将27标记为合数,此时发现9%3=0,循环退出。如果将循环继续下去会出现筛除95=45的情况,而45=153,在15时会被在筛去一次,故不可行
时间复杂度对比(s)
数据量10000000(10^7)
- 普通筛:1.606
- 埃及筛:0,316
- 线性筛:0.098
数据量100000000(10^8)
- 普通筛:28.134
- 埃及筛:3.756
- 线性筛:0.948
本文来自博客园,作者:泥烟,CSDN同名, 转载请注明原文链接:https://www.cnblogs.com/Knight02/p/16045929.html