对筛质数三种方法的理解[普通筛,诶氏筛,线性筛]

这篇博客探讨了三种不同的质数筛选算法:普通筛法、埃拉托斯特尼筛法和线性筛法。通过代码实现和时间复杂度分析,展示了线性筛法在效率上的显著优势,特别是在处理大规模数据时,其时间复杂度为O(n),远低于普通筛法的O(nlogn)和埃拉托斯特尼筛法的O(nloglogn)。对于10^7和10^8规模的数据,线性筛法分别只需要0.098s和0.948s,显著优于其他两种方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//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
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泥烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值