线性筛素数与欧拉函数

对于筛素数问题(即给定一个整数N,求出1~N之间的所有质数,称为质数的筛选问题),我们有一些朴素的算法,比如说枚举法(时间复杂度很高,不推荐),以及埃拉特斯特尼筛法(时间复杂度为O(n loglog n),效率接近线性,但是n过大时会TLE),现在我还有两种筛法,一种是快速线性筛(时间复杂度为O(N)),还有一种是我一年前写出来的(也可能是从哪个题解里看的)玄学算法,在洛谷实测比快速线性筛快(原因下面介绍),下面分别介绍。

一、埃拉特斯特尼筛

先贴代码(由于该算法简明易懂,在此仅贴核心代码)。

void primes(int n){
	memset(v,0,sizeof(v));//v数组用于标记合数,首先清零
	for(int i=2;i<=n;i++)
	{
		if(v[i])continue;//i是合数
		for(int j=i;j<=n/i;j++)//如果i是质数,标记其倍数,用加法是因为加法在理论上比乘法稍快点 
		 v[i*j]=1;
	 } 
}

这是在数据范围要求不高的情况下进行的筛法,其正确性证明可自行百度。但是根据代码可知,埃拉特斯特尼算法中有一个明显的缺陷,在于筛合数时会对某些合数进行重复标记,就是比如说我们筛12时,2*6筛了一次,3*4筛了一次,重复筛除增加了时间复杂度,在竞赛时数据过大可能会造成超时,于是我就使用以下算法进行改进。

二、埃拉特斯特尼改进玄学筛

依旧先贴代码。

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
bool a[100000001];
int m,n,s;
int main()
{
    scanf("%d%d",&m,&n);
    int f=sqrt(m);
    a[1]=1;
    for(int i=4;i<=m;i+=2)  a[i]=1;
    for(int i=3;i<=f+1;i++) 
    {
      if(a[i]==0)//i是质数
      {
        for(int j=i*i;j<=m;j+=i)//倍乘筛合数
        a[j]=1;	
      }
    }
    for(int i&
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值