欧拉筛(线性筛 代码实现以及理解以及重要步骤的证明

欧拉筛(线性筛

老办法,我们先来看看埃式筛

一.埃式筛

埃式筛运用的是一个很简单的算法,“一个素数的整数倍一定是一个合数”,运用这个办法,我们来编写一下埃式筛的程序

const int n = 1000000;
int prime[1000010];//用来存放素数
void aishishai()  
{  
    int i, j;  
    for (i=0; i<n; i++)//方便理解,是素数的初值附为1
		prime[i] = 1;
    prime[0] = prime[1] = 0;//再次方便理解,因为0 1不是素数,所以改成0
    for (i=2; i<n; i++)//开始筛
    {  
        if(prime[i]==0)//如果已经知道他是合数了,就没必要再乘了,直接continue开始下一次循环
			continue;  
        for (j=i*2; j<n; j=j+i)//这里有大佬会做优化,比如j=i*i开始那种。
        					   //但是我们这里理解的是欧拉筛,就不给宁乱脑子了
			prime[ j ] = 0;  
    }
}

我们可以看到,假如我们要把30这个合数筛去,我们有好几种办法筛,例如310,即素数为3的时候筛掉,又可以在215,即素数为2的时候筛掉。这样很明显会浪费时间,所以埃式筛的时间复杂度是o(nloglogn)(埃式筛时间复杂度的证明过程以及埃式筛的改进有(xue)机(hui)会(le)会再发几篇。

二.欧拉筛在埃式筛上的进化

我们要改进埃式筛,就是要阻止这些筛多次的事情发生。所以我们延伸了线性筛。
首先我们要明白一个定理叫做"算数基本定理",也被叫做“整数唯一分解定理

为了让整篇博客通俗易懂而且又不贫瘠和粗略,这里我们只给出结论,证明以及推广可
@百度百科@其他大佬的博客

算数基本定理
任何一个大于1的自然数 N,如果N不为素数,那么N可以唯一分解成有限个质数的乘积

也就是说,我们要找到一个合数的最小质因数,然后用这个最小质因数来把他筛掉,就可了。

最小质因数
一个合数分解出的有限个素数乘积中,最小的那个素数

三.欧拉筛

接下来我们正式进入欧拉筛的代码实现

1.代码思路

1.我们要找到素数
2.确保这个素数是我们要筛的合数的最小质因数
3.利用埃式筛的最基本思想筛掉一些合数

2.代码实现

#include<stdio.h>
int prime[1010];//存放素数 
bool vis[1000000];//检验素数,vis[i]=0代表i是素数, vis[i]=1代表i不是素数 
int main()
{
	int t=0;//1是为了让p[1010]这个数组连续存放素数,自己定义的下标(不用i;
			//2是为了记录素数个数,为后来的循环做条件。 
	for(int i=2;i<=1000;i++)//这里定义的i,既是素数的来源(第13行),也是后面(第20行)用来筛合数的乘数 
	{
		//printf("##i=%d\n",i);
		if(vis[i]==0)//如果是i是素数 
		{
			prime[t]=i;//保存在p[]里 
			t++;
		}
		//printf("t=%d ",t-1);
		for(int j=0;j<t;j++)//开始筛 
		{
			//printf("##i=%d prime[j]=%d i*prime[j]=%d\n",i,prime[j],i*prime[j]);
			vis[prime[j]*i]=true;//把合数筛掉 
			if(i%prime[j]==0)//这里就是埃氏筛和欧拉筛不同之处,优化大多就靠这一条语句(后有证明 
				break;
		}
		//printf("\n------------\n");
	}
	for(int i=0;prime[i]!=0;i++)//输出素数 
		printf("%d  ",prime[i]);
}

其中的一些检验语句陪我埋了,要是看不明白可解开//封印,一个一个值的对看。

3.if(i%p[j]==0) break;

我们这一条语句就保证了最小质因数的条件,也就是说,如果i是prime[j]这个素数的整数倍,那么意味着prime[j+1]不是prime[j+1]*i的最小质因数( 这句话比较难理解,确保你看懂了,在看下面的证明

4.证明----如果i是prime[j]这个素数的整数倍,那么意味着prime[j+1]不是prime[j+1]*i的最小质因数

在这里插入图片描述
很容易可知,prime[j]<prime[j+1],同时我们还不知道k等于几,所以可证明

如果i是prime[j]这个素数的整数倍,那么意味着prime[j+1]不是prime[j+1]*i的最小质因数

在这里插入图片描述

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值