介绍几种常见的质数筛选法

news2024/11/16 7:48:42

质数筛选法

  • 1.暴力筛选法 :smirk:
  • 2.普通优化 :rofl:
  • 3.埃氏筛法:cold_sweat:
  • 4.线性筛选法:scream:

质数:除了1和他本身没有其它因数的正整数就是质数。1不是质数,2是质数。

1.暴力筛选法 😏

  • 原理
    x的质数,令y从2到 x \sqrt[]{x} x (向下取整,比如2.4=2)依次尝试 ,如果x%y=0,那么x不是质数。(2要单独讨论,否则按照这个逻辑2不是质数)。
    • 为什么取 x \sqrt[]{x} x ?
      :如果取到 x \sqrt[]{x} x 还没有找到x的约数,那么就可以断定x一定是质数!!。 x \sqrt[]{x} x * x \sqrt[]{x} x =x,这是一个特殊的位置。可以将这个等式抽象为a * b=x。a和b的关系是你消我涨,即a= x b {x \over b} bx x \sqrt[]{x} x 是a=b的特殊情况,如果a小于等于 x \sqrt[]{x} x 的数里没有x的约数,那么当a大于 x \sqrt[]{x} x 的时候一样没有,因为a小于等于 x \sqrt[]{x} x 的时候,b是大于等于 x \sqrt[]{x} x 的。排除a不是x的约数的同时将b也排除了,因为约数是成对出现的。所以当a大于 x \sqrt[]{x} x 的时候实际上在做重复的计算,相当于把a,b交换了一个位置,实际上当a取值小于等于 x \sqrt[]{x} x 的时候已经把所有可能的约数排除了。
    • 为什么 x \sqrt[]{x} x 要向下取整而不是向上取整?
      :第一个问题解释了,约数是成对出现的,只需要枚举a从2到 x \sqrt[]{x} x 即可,那么b= x a {x \over a} ax同时被考虑到了。如果 x \sqrt[]{x} x 不是整数,那么就向下取整,去掉小数部分,这样可以保证a的枚举没有遗漏(a小于等于 x \sqrt[]{x} x )。如果向上取整,那么a的取值大于 x \sqrt[]{x} x ,b小于 x \sqrt[]{x} x 这个组合实际上之前可能已经被排除了,所以重复计算了一对约数。可能会遗漏约数导致判断错误。
    • 为什么2要单独考虑?
      :代码的逻辑是:从2到 x \sqrt[]{x} x 依次找x的约数,但是2本身可以被2整除,这样就会误判2有约数,所以2要特判一下。
  • 代码
#include<iostream>
#include<cmath>
using namespace std;

bool violence(int n)  //violence  暴力 
{
	if (n == 1)return false;
	if (n == 2)return true;

	for (int i = 2; i <= sqrt(n); i++)   //sqrt函数向下取整的
	{
		if (n % i == 0)return false;   //可以被i整除,不是质数
	}
	return true;
}

int main()
{
	for (int i = 1; i <= 100; i++)  // 找到1-100内的质数
	{
		if (violence(i))cout << i << " ";
	}
	return 0;
}
  • 运行结果
    运行结果

2.普通优化 🤣

  • 优化原理
    • 先贴上代码好理解,否则讲半天不知道在说什么。(看完回到这里😊😊)
    • 如果看懂了跳过,否则看下一行
    • 唯一的难点🙁:为什么当 st[i] == false,则 i 一定是质数呢?
      :当遍历到 i 的时候,2~i-1的所有倍数都被标记成合数了,如果此时i没有被标记,说明i一定是质数。因为i的约数一定是在[2,i-1]的区间内的,而这个区间的所有数的倍数都不能构成i,说明这些数都不是i的约数,那么i就是质数。
int primes[N], cnt;     // primes[]存储所有质数,cnt记录质数的下标
bool st[N];         // st[i]==true表示i不是质数

void get_prime(int n)  //挑选2到n中所有的质数
{
    for(int i = 2; i <= n; i ++)
    {
        if(!st[i])   //当前的数是i,如果st[i]==false,那么说明i这个数一定是质数(理解不了先不解释,看后面的代码)
        	primes[cnt ++] = i;    //存储当前的质数
        
        for(int j = i + i; j <= n; j += i)   //将i的所有倍数都标记为true,因为i的倍数一定不是质数。
            st[j] = true;  
    }
}

3.埃氏筛法😰

  • 数的公理( 两种形式)
    ( 1 ) 任意一个正整数(大于等于 2 ) = x 1 k 1 ∗ x 2 k 2 ∗ . . . . ∗ x n k n (1)任意一个正整数(大于等于2)=x_1^{k_1}*x_2^{k_2}*....*x_n^{k_n} (1)任意一个正整数(大于等于2=x1k1x2k2....xnkn
    ( 2 ) 任意一个正整数(大于等于 2 ) = x 1 k 1 ∗ ( x 2 k 2 ∗ . . . . ∗ x n k n ) (2)任意一个正整数(大于等于2)=x_1^{k_1}*(x_2^{k_2}*....*x_n^{k_n}) (2)任意一个正整数(大于等于2=x1k1(x2k2....xnkn)
    其中 x n x_n xn都是质因数, k n k_n kn是大于等于0的正整数

    • 用人话说就是一个数分解开来,一定是若干个质数相乘,这些分开的数一定是质数😡,如果发现分解的数有合数,那么就没有分解彻底,再把合数分解成质数😡
  • 优化原理
    普通优化是将 i 之前的所有数的倍数都标记,以此判断i是不是合数。但是数的公理第2个形式说明了,一个数必然是由若干个质数的乘积构成的,那么就不需要取将i之前所有数的倍数标记,只需要将i之前的所有质数的乘积标记就可以了。

int primes[N], cnt;     // primes[]存储所有质数,cnt记录质数的下标
bool st[N];         // st[i]==true表示i不是质数

void get_primes(int n)//挑选2到n中所有的质数
{
    for (int i = 2; i <= n; i ++ )
    {
        if (st[i])   //如果st[i]==true,说明i不是质数
        	continue;  
        primes[cnt ++ ] = i;
        for (int j = i + i; j <= n; j += i)  //只要把质数的倍数筛选掉就可以了。
            st[j] = true;
    }
}

4.线性筛选法😱

  • 前集回顾
    埃式筛选法有一个很明显的缺陷,即筛选(标记)合数的时候有大量重复的步骤。比如:
    当 i = 3的时候,将6,9,,,51,,都标记了。当 i = 17 的时候,会标记,34,51,,,发现有重复的项51

  • 目的和公理

    • 目的
      让每个合数只会被筛选一次。
    • 数学公理
      每个数都有一个最小质因数,比如2的最小质因数是2,4的最小质因数是2,5的最小质因数是5,6的最小质因数是2,7的是7,8的是2,9的是3,10的是2,11的是11,12的是2…
  • 原理
    任何数只有一个最小质因数,只要保证每个合数都是最小质因数筛选的,就可以保证不会重复筛选。(有点难以理解)

int primes[N], cnt;     // primes[]存储所有质数,cnt记录质数的下标
bool st[N];         // st[i]==true表示i不是质数

void get_primes(int n)
{
    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;  //筛选的合数primes[j] * i的最小质因数一定是primes[j],就用primes[j]去筛选它
            if (i % primes[j] == 0) //为了避免重复筛选合数。
            //如果i % primes[j] == 0,则primes[j]是i的最小质因数,同时说明primes[j]是i*primes[j]的最小质因数(因为primes[j]是递增的),
            //如果继续循环,下一步就是st[primes[j+1]*i]=true,因为primes[j+1]>primes[j],primes[j+1]<=i,所以primes[j+1]*i的最小质因数仍然是primes[j],
            //但是根据原理,一个数需要被他的最小质因数筛选才不会重复,这里却用primes[j+1]筛选了primes[j+1]*i。重复筛选了。
            	break;
        }
    }
}

i筛掉的数
24
36,9
48
510,15,25
612
714,21,35,49
816
919,27
1020
1122,33,55,77,121

Question区:

1.为什么st[i]=false可以表示是质数(明明下面的for循环和埃式筛选法不一样)
:i= x 1 x_1 x1* x 2 x_2 x2 x 1 x_1 x1表示x的最小质因数, x 1 x_1 x1是[2,i-1]里面的一个质数, x 2 x_2 x2可以是质数也可以是合数。(1) x 2 x_2 x2是质数:我们从代码可以归纳出,当k(2~i-1)是质数的时候,它会筛掉所有的k * primes[j](j从0到cnt-1), 所以i会被[2,i-1]内的某一个质数筛掉。(2) x 2 x_2 x2是合数:我们从代码归纳出,当k是合数的时候,会筛选出[2,k的最小质因子] * primes[j], 而 x 1 x_1 x1是最小质因数,那么一定有一个k会筛选出 x 2 x_2 x2.
2.为什么要if (i % primes[j] == 0)break;
:按照原理来的,每个数都要由他的最小质因数来更新,如果说这一步不退出而是继续循环,那么下一步i * primes[j+1]将被筛选掉,但是i * primes[j+1]的最小质因数是primes[j](因为i不变,上一步i%primes[j]==0且primes[j+1]>primes[j]),而现在i * primes[j+1]由primes[j+1]来筛选了,这样导致筛选过程提前了,后面又会筛选导致重复(当i变大的时候会再次筛选一次)。

线性筛选法还是很难理解的。本质在于:每个数只被筛选一次,且是被去最小质因数筛选的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

官网翻译:LangChain 0.1版本发布,功能介绍

今天&#xff0c;我们非常激动地宣布&#xff0c;LangChain 0.1.0 版本正式发布了&#xff0c;这是我们推出的首个稳定版本。这个版本能够兼容以前的版本&#xff0c;提供了 Python 和 JavaScript 两种编程语言的支持&#xff0c;并通过改进功能和文档&#xff0c;使得我们的产…

【踩坑】JDK1.8 AudioSystem 无法关闭流的问题

文章目录 一、前言二、开始狼人杀嫌疑人1&#xff1a;嫌疑人2&#xff1a; 三、复盘Jdk8原生bug解决方法和原理解析 一、前言 做了一个基于文字转语言的小接口&#xff0c;想删除本地wav文件来着&#xff0c;结果发现删除不了。 很明显被占用了&#xff0c;还是被Java占用了……

【uniapp】遇到的一些问题

一、小程序中textarea ios样式不生效的方法 默认有内边距&#xff0c;加个disable-default-padding"true" 二、uni-data-picker循环使用&#xff0c;一个改了全局的值 换成了uni自带的picker&#xff0c;下面括号里必须有默认值&#xff0c;为空字符串的时候&…

MySql -数据库进阶

一、约束 1.外键约束 外键约束概念 让表和表之间产生关系&#xff0c;从而保证数据的准确性&#xff01; 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数据库 USE db2;-- 创建user用户表 CREATE TABLE USER(id INT PRIMARY KEY …

深入理解 Flink(四)Flink Time+WaterMark+Window 深入分析

Flink Window 常见需求背景 需求描述 每隔 5 秒&#xff0c;计算最近 10 秒单词出现的次数 —— 滑动窗口 每隔 5 秒&#xff0c;计算最近 5 秒单词出现的次数 —— 滚动窗口 关于 Flink time 种类 TimeCharacteristic ProcessingTimeIngestionTimeEventTime WindowAssign…

小程序分销商城,打造高效线上购物体验

小程序商城系统&#xff0c;为您带来前所未有的在线购物体验。它不仅提供线上商城购物、在线下单、支付及配送等功能&#xff0c;还凭借其便捷性成为众多商家的首选。 想象一下&#xff0c;商家可以展示琳琅满目的商品&#xff0c;包括图片、文字描述、价格及库存等详尽信息。而…

C++ 模板 map 和 unordered_map 中,访问不存在的key值,对变量的影响以及返回的结果

map 访问前&#xff1a; 访问后&#xff1a; 测试代码&#xff1a; #include<unordered_map> #include<map> #include<iostream>using namespace std; int main() {map<int,int> map;map[1] 2;map[2] 4;map[3] 6;cout << map[4] << e…

【python】内存管理和数据类型问题

一、内存管理 Python有一个自动内存管理机制&#xff0c;但它并不总是按照期望的方式工作。例如&#xff0c;如果创建了一个大的列表或字典&#xff0c;并且没有删除它&#xff0c;那么这个对象就会一直占用内存&#xff0c;直到Python的垃圾回收器决定清理它。为了避免这种情…

Jmeter+ant+jenkins轻量级接口自动化测试

杀猪不用牛刀&#xff0c;工具没有牛逼高大尚之分&#xff0c;每个工具都有存在的理由&#xff1b;关键是看会不会用&#xff0c;怎么用&#xff0c;有没有用在合适的地方。需要安装的工具&#xff1a; jdk1.8 jmeter3.2 ant1.9&#xff08;蚂蚁&#xff09; jenkins2.1&#…

鸿蒙HarmonyOS学习手册_入门篇

鸿蒙HarmonyOS学习手册_入门篇 文章目录 鸿蒙HarmonyOS学习手册_入门篇入门快速入门开发准备基本概念UI框架应用模型工具准备 构建第一个ArkTS应用&#xff08;Stage模型&#xff09;-快速入门-入门创建ArkTS工程ArkTS工程目录结构&#xff08;Stage模型&#xff09;构建第一个…

websocket介绍并模拟股票数据推流

Websockt概念 Websockt是一种网络通信协议&#xff0c;允许客户端和服务器双向通信。最大的特点就是允许服务器主动推送数据给客户端&#xff0c;比如股票数据在客户端实时更新&#xff0c;就能利用websocket。 Websockt和http协议一样&#xff0c;并不是设置在linux内核中&a…

【理论+实战】带你全面了解 RAG,深入探讨其核心范式、关键技术及未来趋势

写在前面 大家好&#xff0c;关于RAG实战文章已经写了三篇了&#xff0c;有兴趣可以自行去看一下。 用通俗易懂的方式讲解&#xff1a;在 Langchain 中建立一个多模态的 RAG 管道用通俗易懂的方式讲解&#xff1a;大模型 RAG 在 LangChain 中的应用实战用通俗易懂的方式讲解&…

安装ubuntu22.04系统,GPU驱动,cuda,cudnn,python环境,pycharm

需要准备一个u盘&#xff0c;需要格式化&#xff0c;且内存不小于8g 1 下载ubuntu镜像 下载链接&#xff1a; https://cn.ubuntu.com/download/desktop 2下载rufus Rufus - 轻松创建 USB 启动盘Rufus: Create bootable USB drives the easy wayhttps://rufus.ie/zh/ 准备好这…

qt图形化界面开发DAY3

作业&#xff1a; 1> 思维导图 2> 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转…

某查查请求头参数加密分析(含JS加密算法与Python爬虫源码)

文章目录 1. 写在前面2. 请求分析3. 断点分析4. 扣加密JS5. Python爬虫代码实现 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff…

Ubuntu 实时查看显存调用命令 free 及命令详解与原理说明(全)

Ubuntu 实时查看显存调用命令 free 及详解 文章目录 Ubuntu 实时查看显存调用命令 free 及详解1 free 作用1.1 语法&#xff1a;1.2 单独显示例子1.3 组合显示例子 2 输出介绍3 原理解释3.1 buff / cache&#xff08;即 buffer / cache&#xff09;3.1.1 buffer 缓冲区3.1.2 ca…

PYTHON通过跳板机巡检CENTOS的简单实现

实现的细节和引用的文件和以前博客记录的基本一致 https://shaka.blog.csdn.net/article/details/106927633 差别在于,这次是通过跳板机登陆获取的主机信息,只记录差异的部份 1.需要在跳板机相应的路径放置PYTHON的脚本resc.py resc.py这个脚本中有引用的文件(pm.sh,diskpn…

强化学习求解TSP(四):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于奖励的决策问题。它是一种无模型的学习方法&#xff0c;通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策&#xff0c;该函数表示在给定状态下采取某个动作所获…

Linux驱动学习—输入子系统

1、什么是输入子系统&#xff1f; 输入子系统是Linux专门做的一套框架来处理输入事件的&#xff0c;像鼠标&#xff0c;键盘&#xff0c;触摸屏这些都是输入设备&#xff0c;但是这邪恶输入设备的类型又都不是一样的&#xff0c;所以为了统一这些输入设备驱动标准应运而生的。…

使用FFmpeg+EasyDarwin搭建音视频推拉流测试环境

1. 前言 在上一篇文章《使用VS2017在win10 x64上编译调试FFmpeg&#xff08;附源码和虚拟机下载&#xff09;》中&#xff0c;我们讲解了如何搭建FFmpeg源码编译和调试环境。 调试FFmpeg&#xff0c;还需要搭建流媒体服务器。流媒体服务器的作用是通过网络对外提供音视频服务…