数据结构与算法学习笔记----质数

news2024/12/24 21:19:50

数据结构与算法学习笔记----质数

@@ author: 明月清了个风
@@ first publish time: 2024.12.23

ps⭐️质数的判定,分解和筛选,包含了三道题目

什么是质数

在大于 1 1 1的整数中,如果只包含 1 1 1和本身这个两个约数,则称为质数或素数

Acwing 866. 试除法判定质数

[原题链接](866. 试除法判定质数 - AcWing题库)

给定 n n n个正整数 a i a_i ai,判定每个数是否是质数。

输入格式

第一行包含整数 n n n

接下来 n n n行,每行包含一个正整数 a i a_i ai

输出格式

n n n行,其中第 i i i行输出第 i i i个正整数 a i a_i ai是否为质数,是则输出Yes,否则输出No

数据范围

1 ≤ n ≤ 100 1 \le n \le 100 1n100,

1 ≤ a i ≤ 2 31 − 1 1 \le a_i \le 2^{31} - 1 1ai2311

思路

试除法是从定义出发的判断思路,也就是判断有没有除了 1 1 1和这个数本身之外的因数。

有两个注意点:

  1. 如果有一个数 d d d能被数 n n n整除,那么 n / d n / d n/d也能被 n n n整除,因数是成对出现的,因此我们在判断时只需要判断到 n \sqrt{n} n 即可。
  2. 代码中的循环终止条件i <= n / i,而不写成i * i <= n,因为这样存在溢出风险。

因为只要判断到 n \sqrt{n} n ,所以时间复杂度为 O ( n ) O(\sqrt{n}) O(n )

代码

#include <iostream>
#include <cstring>

using namespace std;


bool is_prime(int x)
{
    if(x < 2) return false;
    for(int i = 2; i <= x / i; i ++)
    {
        if(x % i == 0) return false;
    }
    return true;
}

int main()
{
    int n;
    cin >> n;
    
    while(n --)
    {
        int x;
        cin >> x;
        
        if(is_prime(x)) puts("Yes");
        else puts("No");
    }
    
    return 0;
}

Acwing 867. 分解质因数

[原题链接](867. 分解质因数 - AcWing题库)

给定 n n n个正整数 a i a_i ai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

输入格式

第一行包含整数 n n n

接下来 n n n行,每行包含一个正整数 a i a_i ai

输出格式

对于每个正整数,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。

每个正整数的质因数全部输出完毕后,输出一个空行。

数据范围

1 ≤ n ≤ 100 1 \le n \le 100 1n100,

2 ≤ a i ≤ 2 × 1 0 9 2 \le a_i \le 2 \times 10^9 2ai2×109

思路

同样使用试除法进行分解,对于碰到的每个质因数都将他除干净记录次数,具体的看代码吧

时间复杂度为 O ( n ) O(\sqrt{n}) O(n ),但不一定会到这个数,这是最坏的情况。

代码

#include <iostream>
#include <cstring>

using namespace std;

void divide(int x)
{
    for(int i = 2; i <= x / i; i ++)
    {
        if(x % i == 0)   // 如果是一个因数,则记录次数,这里能够保证这个因数是质因数,因为每次碰到了因数都会除干净,并且从2开始就是质因数
        {
            int s = 0;
            while(x % i == 0)
            {
                x /= i;
                s ++;
            }
            cout << i << ' ' << s << endl;
        }
    }
    
    if(x > 1) cout << x << ' ' << 1 << endl;  // 一个数最多有一个大于根号x的质因数,如果有两个乘起来就大于x了,因此最后还要判断一下
    puts("");
}

int main()
{
    int n;
    cin >> n;
    
    while(n --)
    {
        int x;
        cin >> x;
        
        divide(x);
    }
    return 0;
}


Acwing 868. 筛质数

[原题链接](868. 筛质数 - AcWing题库)

给定一个正整数 n n n,请你求出 1 ∼ n 1 \sim n 1n中质数的个数

输入格式

共一行,包含整数 n n n

输出格式

共一行,包含一个整数,表示 1 ∼ n 1 \sim n 1n中质数的个数

数据范围

1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1n106

思路

首先肯定还是从定义出发,只要筛选掉所有的合数剩下的就是质数了,因此可以将从小到大开始,将每个数的倍数就筛掉,代码如下

void get_primes(int n)
{
    for(int i = 2; i <= n; i ++)
    {
        if(!st[i]) primes[cnt ++] = i;   // 遍历的过程中碰到没有被筛掉的数说明是质数
        for(int j = i + i; j <= n; j += i)   // 将每个数的x倍都筛掉
            st[j] = true;   // 筛掉的数标记为true
    }
}

这样的筛选时间复杂度为 O ( n ln ⁡ n ) = O ( n log ⁡ e n ) ≈ O ( n log ⁡ n ) O(n \ln n) = O(n \log_{e} n) \approx O(n \log n) O(nlnn)=O(nlogen)O(nlogn)

这里可以做出一点优化,我们在筛选时可以只用质数去筛选,将第二重循环放在判断里面,这样的话所有的合数都会被一个质数筛掉,根据质数定理: 1 ∼ n 1 \sim n 1n中有 n ln ⁡ n \frac{n}{\ln n} lnnn个质数,在上面的筛选中时间复杂度为 n ( 1 2 + 1 3 + ⋯ + 1 n ) ≈ n ln ⁡ n n(\frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n}) \approx n \ln n n(21+31++n1)nlnn,但是只用质数筛后,我们本来要计算 n n n个数,现在只需要计算 n ln ⁡ n \frac{n}{\ln n} lnnn个数,因此时间复杂度变为 n ln ⁡ n ln ⁡ n ≈ n \frac{n \ln n}{\ln n} \approx n lnnnlnnn,也就是 O ( n ) O(n) O(n),但是这是一个粗略估计,真实的复杂度为 O ( n log ⁡ log ⁡ n ) O(n \log {\log n}) O(nloglogn),这样的筛选会比上面的朴素版本快三倍左右,这就是埃氏筛法

void get_primes(int n)
{
    for(int i = 2; i <= n; i ++)
    {
        if(!st[i])
        {
            primes[cnt ++] = i;   // 遍历的过程中碰到没有被筛掉的数说明是质数
            for(int j = i + i; j <= n; j += i)   // 将每个数的x倍都筛掉
            	st[j] = true;   // 筛掉的数标记为true
        }
    }
}

对于上述筛法还可以进一步优化,因为在上面的筛选过程中,一个合数可能会被筛选多次,比如对于 6 6 6来说,他会被 2 2 2 3 3 3分别筛选一次,那么如果省去这样多余的步骤呢,线性筛法完成了这样的优化,**通过优化合数的标记方式,使每个合数都只被筛选一次,从而达到了线性时间复杂度。**下面首先给出线性筛选的代码

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;
            if(i % primes[j] == 0) break;
        }
    }
}

为什么叫线性筛选

  1. 如果 i i i是质数,那么会被记录在primes[]数组里

  2. 如果 i i i是合数,他会被其最小质因子标记为合数。

    • 为什么是最小质因子

      因为我们从小达到遍历所有质数primes[],有两种情况:

      a. 当i % primes[j] == 0时跳出循环,此时primes[j]肯定是i的最小质因子;

      b. 当i % primes[j] != 0时,我们会将primes[j] * i标记为合数,对于primes[j] * i来说,因为i % primes[j] != 0并且primes[j]是从小到大枚举的,因此primes[j]肯定不是i的最小质因子,且小于其最小质因子,但是对于primes[j] * i来说,因为i的最小质因子大于primes[j],因此primes[j] * i的最小质因子为primes[j]

      这样就确保了每个合数都只会被其最小质因子筛掉,每个数又只有一个最小质因子,因此整个算法是线性的。

代码

#include <iostream>
#include <cstring>

using namespace std;

const int N = 1000010;

int n;
int primes[N], cnt;
bool st[N];

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;
            if(i % primes[j] == 0) break;
        }
    }
}

int main()
{
    cin >> n;
    
    get_primes(n);
    
    cout << cnt << endl;
    
    return 0;
}

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

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

相关文章

Windows下ESP32-IDF开发环境搭建

Windows下ESP32-IDF开发环境搭建 文章目录 Windows下ESP32-IDF开发环境搭建一、软件安装二、搭建IDF开发环境2.1 安装VS Code插件&#xff1a;2.2 配置ESP-IDF插件&#xff1a;2.3 下载例程源码&#xff1a; 三、编译和烧录代码四、Windows下使用命令行编译和烧录程序4.1 配置环…

6UCPCI板卡设计方案:8-基于双TMS320C6678 + XC7K420T的6U CPCI Express高速数据处理平台

基于双TMS320C6678 XC7K420T的6U CPCI Express高速数据处理平台 1、板卡概述 板卡由我公司自主研发&#xff0c;基于6UCPCI架构&#xff0c;处理板包含双片TI DSP TMS320C6678芯片&#xff1b;一片Xilinx公司FPGA XC7K420T-1FFG1156 芯片&#xff1b;六个千兆网口&#xff…

c++--------------------------------接口实现

引用参数 引用的基本概念 在C中&#xff0c;引用是一个别名&#xff0c;它为已存在的变量提供了另一个名字。引用的声明格式为类型& 引用名 变量名;。例如&#xff0c;int num 10; int& ref num;&#xff0c;这里ref就是num的引用&#xff0c;对ref的操作等价于对nu…

docker run命令大全

docker run命令大全 基本语法常用选项基础选项资源限制网络配置存储卷和挂载环境变量重启策略其他高级选项示例总结docker run 命令是 Docker 中最常用和强大的命令之一,用于创建并启动一个新的容器。该命令支持多种选项和参数,可以满足各种使用场景的需求。以下是 docker ru…

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入&#xff0c;3568采集并显示至hdmi RKVICAP 驱动框架说明 RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转&#xff0c;以及控制 subdevice(如 mipi dphy 及 sensor) 的上下电等功能。 对于RK356X 芯片而言&#xff0c; VICAP…

怎么在idea中创建springboot项目

最近想系统学习下springboot&#xff0c;尝试一下全栈路线 从零开始&#xff0c;下面将叙述下如何创建项目 环境 首先确保自己环境没问题 jdkMavenidea 创建springboot项目 1.打开idea&#xff0c;选择file->New->Project 2.选择Spring Initializr->设置JDK->…

springboot476基于vue篮球联盟管理系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统篮球联盟管理系统信息管理难度大&#xff0c;容错率低&am…

蓝桥杯嵌入式备赛教程(1、led,2、lcd,3、key)

一、工程模版创建流程 第一步 创建新项目 第二步 选择型号和管脚封装 第三步 RCC使能 外部时钟&#xff0c;高速外部时钟 第四步晶振时钟配置 由数据手册7.1可知外部晶振频率为24MHz 最后一项设置为80 按下回车他会自动配置时钟 第五步&#xff0c;如果不勾选可能程序只会…

步进电机位置速度双环控制实现

步进电机位置速度双环控制实现 野火stm32电机教学 提高部分-第11讲 步进电机位置速度双环控制实现(1)_哔哩哔哩_bilibili PID模型 位置环作为外环,速度环作为内环。设定目标位置和实际转轴位置的位置偏差,经过位置PID获得位置期望,然后讲位置期望(位置变化反映了转轴的速…

devops和ICCID简介

Devops DevOps&#xff08;Development 和 Operations 的组合&#xff09;是一种软件开发和 IT 运维的哲学&#xff0c;旨在促进开发、技术运营和质量保障&#xff08;QA&#xff09;部门之间的沟通、协作与整合。它强调自动化流程&#xff0c;持续集成&#xff08;CI&#xf…

Apache RocketMQ 5.1.3安装部署文档

官方文档不好使&#xff0c;可以说是一坨… 关键词&#xff1a;Apache RocketMQ 5.0 JDK 17 废话少说&#xff0c;开整。 1.版本 官网地址&#xff0c;版本如下。 https://rocketmq.apache.org/download2.配置文件 2.1namesrv端口 在ROCKETMQ_HOME/conf下 新增namesrv.pro…

数据结构:算法篇:快速排序;直接插入排序

目录 快速排序 直接插入排序 改良版冒泡排序 快速排序 理解&#xff1a; ①从待排序元素中选定一个基准元素&#xff1b; ②以基准元素将数据分为两部分&#xff1a;&#xff08;可以将&#xff1a;大于基准元素放左&#xff0c;小于基准元素放右&#xff09; ③对左半部分…

运维工程师面试系统监控与优化自动化与脚本云计算的理解虚拟化技术的优点和缺点

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

如何打造用户友好的维护页面:6个创意提升WordPress网站体验

在网站运营中&#xff0c;无论是个人博主还是大型企业网站的管理员&#xff0c;难免会遇到需要维护的情况。无论是服务器迁移、插件更新&#xff0c;还是突发的技术故障&#xff0c;都可能导致网站短暂无法访问。这时&#xff0c;设计维护页面能很好的缓解用户的不满&#xff0…

postman读取文件执行

要从文件获取的变量 text 在pre-request 中写从文件获取数据的脚本。脚本实现了&#xff0c;设置了text默认值&#xff0c;从文件读取text列&#xff0c;将text存入环境变量 //获取text参数 var text "济南天气"; if(data.text){ text data.text } pm.environment.…

37. Three.js案例-绘制部分球体

37. Three.js案例-绘制部分球体 实现效果 知识点 WebGLRenderer WebGLRenderer 是Three.js中的一个渲染器类&#xff0c;用于将3D场景渲染到网页上。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数&#xff0c;可选。 常用…

【Rust自学】4.4. 引用与借用

4.4.0 写在正文之前 这一节的内容其实就相当于C的智能指针移动语义在编译器层面做了一些约束。Rust中引用的写法通过编译器的约束写成了C中最理想、最规范的指针写法。所以学过C的人对这一章肯定会非常熟悉。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文…

电脑使用CDR时弹出错误“计算机丢失mfc140u.dll”是什么原因?“计算机丢失mfc140u.dll”要怎么解决?

电脑使用CDR时弹出“计算机丢失mfc140u.dll”错误&#xff1a;原因与解决方案 在日常电脑使用中&#xff0c;我们时常会遇到各种系统报错和文件丢失问题。特别是当我们使用某些特定软件&#xff0c;如CorelDRAW&#xff08;简称CDR&#xff09;时&#xff0c;可能会遇到“计算…

C# 基本信息介绍

总目录 前言 对 C# 做一个基本信息介绍&#xff0c;让我们对 C# 有个基本的认识。 在进行本文的阅读之前&#xff0c;可以瞧瞧 编程基础知识简述 简单的入个门儿。 一、C# 1. C# 概述 C#是由微软公司发布的一种由C和C衍生出来的面向对象的编程语言。 2. C# 详细介绍 C#&am…

『Linux学习笔记』FRPC 详细介绍及配置解析!

『Linux学习笔记』FRPC 详细介绍及配置解析&#xff01; 文章目录 一. FRPC 详细介绍及配置解析FRPC 的主要功能FRPC 配置文件解析全局配置代理配置第一个代理服务第二个代理服务 配置文件整体工作流程常见配置项说明FRPC 的使用步骤注意事项结论 二. 参考文献 一. FRPC 详细介…