素数筛法

算法之素数筛法 方法一 //判断是否是一个素数 int IsPrime(int a){ //0,1,负数都是非素数 if(a <= 1){ return 0; } //计算枚举上界,为防止double值带来的精度损失,所以采用根号值取整后再加1,即宁愿多枚举一个,也不愿少枚举一个数 int bound = (int)sqrt(a) + 1; for(int i = 2;i < b 阅读详情

素数定义

质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。

素数判断

 

设n为要判断的数。按照定义,判断n是否能被2~n-1中任意一个数整除即可。时间复杂度为O(n)

bool prime(int n)
{
    if(n==1)                    //如果n为1,则n不是素数返回false
        return false;
    for(int i = 2; i < n; i++)
    {
        if(n%i==0)              //如果n被除1以及n以外的自然数整除那么n不是素数,返回false
            return false;
    }
    return true;                //返回true
}

这里有一种升级版本

只需要判断n是否能被2~√n中任意一个数整除即可。这是为什么呢?

举个例子,一个合数n能被i整除,商为j,那么一定存在i*j=n,一定存在i<=√n<=j,所以如果一个数在2~√n范围内没有被整除,那么这个数一定是素数

该升级版本时间复杂度为O(√n)

bool prime(int n)
{
    if(n==1)                    //如果n为1,则n不是素数返回false
        return false;
    for(int i = 2; i*i <= n; i++)
    {
        if(n%i==0)              //如果n被除1以及n以外的自然数整除那么n不是素数,返回false
            return false;
    }
    return true;                //返回true
}

 

素数筛法

当我们需要求一个区间[a,b]范围内的所有素数时,如果这个区间范围很大,就需要用到素数筛法了。

素数筛法就是根据已经求出来的素数,来将素数的倍数筛去,因为素数的倍数一定不是素数

埃氏筛法

思想:从2开始,将每个质数的倍数都标记成合数,以达到筛选素数的目的

代码:

int vis[maxn];                              //用来标记素数,素数标记为0,非素数为1
bool prime()
{
    memset(vis,0,sizeof(vis));              //初始都是素数
    vis[0]=vis[1]=1;                        //0和1都不是素数
    for(int i = 2; i <= maxn; i++)          //2一定是素数,所以从2开始可以不断筛出合数
    {
        if(!vis[i])                         //如果i是素数,让i的所有倍数都不是素数
        {
            for(int j = i*i; j<=maxn; j+=i)  //
            {
                vis[j] = 1;
            }
            cout<<endl;
        }
    }
}

 这里有一个优化,j并不是从i+i开始的,这是因为i*(2-i-1)在2~i-1时已经筛去。

存在的问题:

同一个合数可能被不同的素数重复筛出。

以图中的12为例,12是素数2和素数3的倍数,2*6=12  3*4=12,所以12就被筛了两次。

那么如何保证每个合数只被筛选一次呢?只需要保证每个合数被它的最小质因子筛选。这也就是欧拉筛法的思想

 

欧拉筛法

思路:在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 20;
int vis[maxn];                              //用来标记素数,素数标记为0,非素数为1
int prime[maxn];                            //保存素数
bool Prime()
{
    int cnt = 0;                            //记录prime中素数的数量
    memset(vis,0,sizeof(vis));              //初始都是素数
    vis[0]=vis[1]=1;                        //0和1都不是素数
    for(int i = 2; i <= maxn; i++)          //2一定是素数,所以从2开始可以不断筛出合数
    {
        if(!vis[i])                         //如果i是素数,让i的所有倍数都不是素数
        {
            prime[cnt++]=i;
        }
        //以最小质因子的方式去筛选,而不是以素数的倍数的方式
        for(int j = 0; j<cnt&&i*prime[j]<=maxn; j++)
        {
            vis[i*prime[j]] = 1;
            if(i%prime[j]==0)
                break;
        }
        cout<<endl;
    }
}
int main()
{
    Prime();
    return 0;
}

①vis[i*prime[j]]不是用素数的倍数筛选,而是用prime数组中从小到大的素数作为最小质因子筛选。

②对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。

时间复杂度分析:求解[1,n]区间中的素数,每个合数只会被筛选一次,就是说每个数只会被标记一次,因此时间复杂度为O(n)

 

参考博文:https://blog.youkuaiyun.com/qq_39763472/article/details/82428602

筛法求素数 ...   一般求素数都是暴力求解,这样效率不高,今天就总结一下筛法求素数,这是一种较高效的算法,具体如下: 用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。 用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛... 阅读详情

相关推荐

素数筛法(Eratosthenes筛法)

介绍 Eratosthenes筛法,又名埃氏筛法,对于求1~n区间内的素数,时间复杂度为n log n,对于106 以内的数比较合适,再超出此范围的就不建议用该方法了。 筛法的思想特别简单: 对于不超过n的每个非负整数p, 删除2p, 3p, 4p,…, 当处理完所有数之后, 还没有被删除的就是素数。 代码 void init() { int cnt=0; for(int i=0;...

无论多么困难,也要熬下去!!! 909

三大素筛原理

欧拉筛 #include<bits/stdc++.h> using namespace std; const int N = 100000100; int cnt, n; int prime[N]; bool on[N]; int main() { scanf("%d", &n); on[0] = on[1] = 1; //0和1不是素数 for(int i = 2...

qq_45560445的博客 367

stm32h743的hrtim使用生成pwm波

HRTIM(High-Resolution Timer)是一种高精度定时器,其时钟频率可直接与CPU主频同步,达到480MHz。相比之下,其他传统定时器需挂载在APB总线上,受总线频率限制,最高仅支持240MHz。这种直接时钟同步机制显著提升了定时器的分辨率和精度。

d13211322的博客 1610

算法篇——素数筛

埃氏筛、欧拉筛的讲解

lcx0128的博客 3118

AppFlow实战:零代码将Dify接入企业微信的完整指南

本文提供了一份零代码将Dify AI应用接入企业微信的完整实战指南。通过使用阿里云AppFlow作为无代码连接器,详细讲解了从获取Dify API密钥、创建企业微信应用到配置自动化流程的全过程,帮助团队快速将AI能力无缝融入日常协作,大幅提升工作效率。

php55的博客 808

使用电荷放大器处理压电加速度计输出

电阻器 R p模拟传感器的绝缘电阻,为产生的电荷创建泄漏路径。在此图中,顶部波形显示传感器产生的电荷,而底部波形显示电荷放大器的输出。这需要具有大输入阻抗的放大级,以防止产生的电荷通过与传感元件并联的放大器的输入阻抗泄漏。换句话说,电荷放大器补偿传感器产生的电荷 q p ,反馈电容器 C F中具有相反极性的等量电荷。因此,任何与传感器并联的绝缘电阻,如电缆的绝缘电阻或传感器的漏电电阻Rp,都不能流过电流。漂移是指电荷放大器输出在一段时间内发生的变化,而不是由被测物理参数的变化(我们讨论的加速度)引起的。

weixin_45260069的博客 3905

素数的两种筛法

埃氏筛 埃氏筛法求前n个数中的素数个数 首先,我们将2到n范围内的所有整数写下来。 先将2的倍数都筛去 其中最小的素数2是,于是我们将表中所有2的倍数都划去。3为距离2最近的没有被筛去的数,所以3不能被除1外比3更小的数整除,故3为素数。再将表中所有3的倍数都划去。像这样反复操作,就能枚举n以内的素数。 如果要依次判断n前的数字是否为素数,最优也要 O(n√n)的时间复杂度 但采用埃氏筛可以将时间复杂度降低为 O(nloglogn) 代码实现 #include <iostream&g

qq_65542034的博客 1452

Manus通用AI智能体完全使用指南(2025最新版)——从注册到高阶技巧全解析

Manus通用AI智能体完全使用指南(2025最新版)——从注册到高阶技巧全解析

m0_69718028的博客 8116

素数筛(彻底理解)

一.什么是素数 长话短说:因数只有1和本身的正整数,(但素数不包含1). 比如 2 ,3,5,7… 二.如何判断一个数是素数 用1中的定理,也就是说,如果某个大于1的正整数与任何小于等于它的正整数的最大公因数都是1,则为素数 咳咳咳…扯远了,我们的重心不在这里,重点在下面: 三.什么是素数筛 首先,给你一个区间的正整数,让你求在这段区间内有哪些素数? 这里,我们就可以用“筛选的方法”筛去不是素数的正整数(也就是合数)剩下的就是素数了,但不同的筛法效率也是不一样的 1. 最直接的筛法 获取1到n以内的所有素

YSJ367635984的博客 2万+

Python:同花顺全数据接口

# -*- coding: utf-8 -*- from iFinDPy import * from datetime import datetime import pandas as pd import time as _time import json from threading import Thread,Lock,Semaphore import requests sem = Semaphore(5) # 此变量用于控制最大并发数 dllock = Lock() #此变量用来控制实时行情推

代码过客 4万+

高数15种常见特殊曲线:星形线、心形线、摆线、对数螺线、双曲螺线、阿基米德螺线、伯努利双纽线、三叶玫瑰线、四叶玫瑰线、六叶玫瑰线、三次抛物线、半立方抛物线、箕舌线、蔓叶线、笛卡儿叶形线、概率曲线

4.1 对数螺线(等角螺线、生长螺线)三叶玫瑰线、四叶玫瑰线、六叶玫瑰线。​7.2 半立方抛物线(尼尔曲线)10.笛卡儿叶形线(茉莉花瓣曲线)常考选择题、填空题,大题也涉及。​4.2 双曲螺线(倒数螺线)11.阿基米德螺线(等速螺线)3.摆线(圆滚线、旋轮线)5.双纽线(伯努利双纽线)1.星形线(四尖瓣线)2.心形线(心脏线)..................

刘鑫磊 1万+

筛选法与试除法 判断素数

素数的求解方法 第一种:试除法 第二种:筛选法 ------试除法------- 顾名思义:求一个数X是不是素数,就试用小于x大于1区间的自然数,只要有一个能整除,那么x就不是素数,否则就是。 以输出100—200之间的素数为例 #include <stdio.h> int main() { int i = 1; int count = 0; //定义一个计数器来统计素数的个数 for (i = 100;i <= 200;i++) { int j = 2; for (j

crawer 1135

如何让 Mac mini 24小时不休眠运行 OpenClaw

如果 OpenClaw 每 5-10 分钟自动退出,launchd 连续 4 次快速重启后会判定为崩溃循环并卸载服务。:方案一(pmset)+ 方案三(launchd)组合使用,既防止系统休眠,又保证 OpenClaw 开机自启和崩溃自动恢复。:caffeinate 只在进程运行期间有效,终端关闭或进程结束后系统恢复正常睡眠策略。这条命令会自动创建 launchd plist 并启用服务,是最推荐的方式。替换为你的实际用户名路径,Node.js 路径也要改成你自己的。确保 plist 中有。

Maynor的博客 2202

三种素数筛法(普通筛法、埃氏筛法、欧拉筛法)

素数筛法 一般筛法: 一般筛法适用于单个元素的检验,就是简单地对于一个元素 n 从2至 sqrt(n)进行检验能否整除,有一个就不是素数。 代码如下: //原始筛选法->适用于单个元素的检验 bool isprime_A(int n) { for(int i = 2;i < sqrt(n);i++) { if(n % i == 0) { return false; } } return tru

hhyer的博客 8739

初探802.11协议(6)——Wi-Fi 6新特性简介

Wi-Fi 6新机制(特性)介绍

FanFF的博客 1522

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

素数筛法总结

素数筛法总结

ZhuRanCheng的博客 1451

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

素数筛法:埃氏筛法与线性筛法

时间复杂度是Onloglogn。如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。例如:考虑 2 时, 我们把 4, 6, 8, 10, 12, 14, 16, 18 … 均标记为合数。考虑 3 时, 我们把 6, 9, 12, 15, 18, 21, 24, 27 … 均标记为合数。考虑 4 时, 我们把 8, 12, 16, 20, 24, 28, 32, 36 … 均标记为合数。

c的博客 1879

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

素数筛法 - 欧拉筛法

素数筛法 - 欧拉筛法 素数的筛法有几种,这次主要谈一下欧拉筛法 1.暴力求素数        时间复杂度 : O(n2) 稍微优化一下 :缩小数据范围从 n 优化到√n        时间复杂度 : 自然也就从 O(n2) 到 O(√n) 2.著名的埃式筛法        时间复杂度 : O(nloglogn) 而要谈的欧拉筛法则是在埃式筛法的基础上再次进行优化 3.欧拉筛法      ...

qq_43701555的博客 2266

素数筛法:高效求解素数问题的利器

埃氏筛法是一种简单有效的素数筛选方法,通过不断标记合数来得到素数表,时间复杂度为 O (N log log N),空间复杂度为 O (N)。优化的埃氏筛法在埃氏筛法的基础上减少了不必要的计算,提高了效率,但时间复杂度仍为 O (N log log N)。线性筛法是最优化的筛法,保证每个合数只被标记一次,时间复杂度降低到 O (N),空间复杂度为 O (N)。

m0_57836225的博客 1423

素数筛法C++代码

素数筛法C++代码 这种素数筛法时间复杂度大约为O(n*sqrt(n)),略差于最优线性筛法的O(n),但是面对一般的OJ题目足够用了,而且简单易记。 使用素数筛法,输出0~Max之间的所有素数 #include &lt;iostream&gt; using namespace std; #define Max 100 //0~max_num之间的素数 int prim...

AlwaySimple的博客 4775

素数筛法求素数

素数筛类似于打表标记,预先处理掉非素数的数,即素数的倍数(任意非素数都可以由几个素数相乘得到),于是效率比暴力求解快得多。 埃氏筛法的效率为O(n loglog n),简单易懂,但是会重复标记,比如当i为2时,6会被标记掉,然而当i为3时,6又会被重复标记,这样的重复访问加大了时间复杂度,于是有了欧拉筛。 1 #include<iostream> 2 #include&l...

weixin_30662849的博客 237
上一篇: L3-001 凑零钱 (30分)
下一篇: [蓝桥杯][历届试题]九宫重排
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值