数学知识--(质数,约数)

本文用于个人算法竞赛学习,仅供参考

目录

一.质数的判定

二.分解质因数

三.质数筛

1.朴素筛法

 2.埃氏筛法

3.线性筛法

 四.约数

1.求一个数的所有约数

2.约数个数和约数之和

3.欧几里得算法(辗转相除法)-- 求最大公约数


一.质数的判定

质数:质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的数。常见的质数有2, 3, 5, 7, 11等。质数也被称为素数。

试除法:时间复杂度:O(n^ 1/2)

bool is_prime(int n)
{if (n < 2)return false;for (int i = 2; i <= n / i; i++) //如果存在 a ÷ b = c , 那么就有 a ÷ c = b; {if (n % i == 0){return false;}}return true;
}

二.分解质因数

 

试除法:时间复杂度:O(n^ 1/2)

//存放分解后质数的个数
unordered_map<int, int> primes;void divide(int n)
{//从2开始试除for (int i = 2; i <= n / i; i++)// i^2 <= n{//合数进不来,因为被前面的质数约去了if (n % i == 0){while (n % i == 0){primes[i]++;n /= i;}}}if (n > 1)primes[n]++;
}int main()
{divide(84);for (auto prime: primes){cout << prime.first << ':' << prime.second << endl;}return 0;
}

三.质数筛

问题:给定一个n,筛出2~n的所有质数

1.朴素筛法

假设一个数n,它的因数有a, 那么n的因数a一定小于n,所以只需要通过a的倍数就能筛掉n,所以朴素筛法就是从2到n筛掉它们的倍数,最后剩下的就是质数。

时间复杂度:N(1 + 1/2 + 1/3 + ... + 1/n) = N*lnN,  O(N*lnN);

 可以发现同一个数可能会被筛掉多次,当样本个数非常多的时候是非常浪费时间的,要如何优化降低对一个数筛的次数呢?

 2.埃氏筛法

埃氏筛法是对上面朴素筛法的优化,只筛掉质数的倍数,来减少筛掉同一个数的次数。

埃氏筛法(Sieve of Eratosthenes)是一种用来找出一定范围内所有素数的算法。其基本思想是从2开始,不断地将质数的倍数标记为非质数,最终剩下的即为质数。

 筛掉4的倍数时,其实在筛掉2的倍数时就筛掉了,因为4是2的倍数,4的倍数也是2的倍数,所以4就没必要再去筛掉它的倍数了;对于一个合数,总会有它的质数代替它来筛掉它的倍数。

质数定理指出,小于给定数n的质数个数约为 n / ln(n)。

优化后时间O(N*loglogN)

const int N = 100;
int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉void get_primes(int n)
{for (int i = 2; i <= n; i++){if (st[i]) continue;primes[cnt++] = i;for (int j = i + i; j <= n; j += i)st[j] = true;}
}

 

 我们发现还是存在对同一个数多次筛掉的情况,如12被2和3筛掉两次,还能再优化吗?

3.线性筛法

线性筛法是一种在O(n)的复杂度情况下,筛选出2~n的所有质数。
它的原理是,从2开始,每次找到一个最小的质数,然后把它的倍数都标记为非质数,即每个数合数只会被它的最小质因数筛掉。

比如上面的埃氏筛法,12会被2和3筛两次,线性筛法只会通过12的最小的质数2来筛掉。

最外层for循环遍历2~n,primes保存2~i的质数,内层for循环从小枚举质数

1.对于   primes[j] <= n / i;

如果i是合数,会走到 if (i % primes[j] == 0) break  结束掉

如果i是质数,会走到 primes[j] == i 后结束掉

所以不用担心存在越界问题 

2.对于  if (i % primes[j] == 0) break;

若 i % primes[j] != 0, primes[j]一定小于i的最小质因子,primes[j] 一定是primes[j] * i 的最小质因子,因为primes从小到大枚举,且primes[j] 小于i

若i % primes[j] == 0,primes[j] 一定是i的最小质因子,primes[j] 一定是primes[j] * i 的最小质因子,因为primes从小到大枚举,且primes[j] 小于i

如果i % primes[j] == 0,就应该break了,为什么?

已知i % primes[j] == 0,就说明i是合数,i已经再前面通过k * primes[j] 筛掉了;

假设我们没有break,走到primes[j + 1], 会有 i * primes[j + 1], 代入得 k * primes[j] * primes[j + 1],很明显primes[j] < primes[j + 1], 说明一个数已经被primes[j] 筛掉过了,再通过primes[j]筛就重复了。

3.对于每一个合数x,一定会被筛掉,假设x的最小质因子为p,当i 遍历到x / p时,x一定会被筛掉。

4.每一个合数都会被它的最小质数筛掉,说明每个数只会被筛一次,所以是线性的,时间复杂度是O(n)。

int primes[N], cnt;     // primes[]存储所有素数
bool st[N];         // st[x]存储x是否被筛掉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 <= n / i, 看i 是否是约数

vector<int> get_divisors(int n)
{vector<int> result;for (int i = 2; i <= n / i; i++){if (n % i == 0){result.push_back(i);//避免加入同一个数if (n / i != i)result.push_back(n / i);}}sort(result.begin(), result.end());return result;
}

2.约数个数和约数之和

给定一个数N,求N的约数个数

将N进行质因数分解p,有N = p1^c1 * p2^c2 * ... *pk^ck
对于每个质数p,c可以取0~c,则约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)

 思路:

由N = p1^c1 * p2^c2 * ... *pk^ck,约数和为(p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)

p比较好求,直接分解质因数就行,问题是(pk^0 + pk^1 + ... + pk^ck)要怎么求?

假设 t = 1,存在操作 t = p * t + 1;

则有t = p * 1 + 1 = p + 1

t = p * (p + 1) + 1 = p^2 + p + 1

t = p * (p^2 + p + 1) + 1 = p^3 + p^2 + p^1 + 1

……

typedef long long LL;
int mod = 1e9 + 7;int main()
{unordered_map<int, int> primes;int n;cin >> n;while (n--){int a;cin >> a;//对每个数进行质因数分解for (int i = 2; i <= a / i; i++){if (a % i == 0){primes[i]++;a /= i;}}if (a > 1)primes[a]++;}LL result = 1;for (auto prime : primes){LL t = 1;int a = prime.first, b = prime.second;while (b--){t = (t * a + 1) % mod;}result = result * t % mod;}cout << result << endl;return 0;
}

常见模运算

(a * b) mod c = ((a mod c) * (b mod c)) mod c
(a + b) mod c = ((a mod c) + (b mod c)) mod c
(a - b) mod c = ((a mod c) - (b mod c)) mod c
(a ^ b) mod c = ((a mod c) ^ b) mod c
(a / b) mod c != ((a mod c) / (b mod c)) mod c除法的模运算不满足这样的等式

3.欧几里得算法(辗转相除法)-- 求最大公约数

gcd(a, b) = gcd(b, a mod b);

gcd代表最大公约数

int gcd(int a, int b)
{//if (a < b) swap(a, b);//这一步不需要,因为会自己调整,比如gcd(6,16),下一次递归就变成了gcd(16,6)return b ? gcd(b, a % b) : a;
}

 

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

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

相关文章

新型智慧城市大数据解决方案(附下载)

随着云计算、大数据、移动互联网等技术的发展&#xff0c;由城市运行产生的交通、环境、市政、商业等各领域数据量巨大&#xff0c;这些数据经过合理的分析挖掘可产生大量传统数据不能反映的城市运行信息&#xff0c;已成为智慧城市的重要资产。 在大数据时代&#xff0c;数据信…

理解main方法的语法

由于JVM需要调用类的main()方法&#xff0c;所以该方法的访问权限必须是public&#xff0c;又因为JVM在执行main()方法时不必创建对象&#xff0c;所以该方法必须是static的&#xff0c;该方法接收一个String类型的数组参数&#xff0c;该数组中保存执行Java命令时传递给所运行…

问题解决:写CSDN博文时图片大小不适应,不清晰,没法排版

项目环境&#xff1a; Window10&#xff0c;Edge123.0.2420.65 问题描述&#xff1a; 当我在CSDN写博文的时候&#xff0c;会经常插入一些图片&#xff0c;但有时候我插入的图片太大了&#xff0c;影响了整体排版。 比如我加入了一张图片&#xff0c;就变成了下面这个样子&…

PEFT-LISA

LISA是LoRA的简化版&#xff0c;但其抓住了LoRA微调的核心&#xff0c;即LoRA侧重更新LLM的底层embedding和顶层head。 根据上述现象&#xff0c;LISA提出两点改进&#xff1a; 始终更新LLM的底层embedding和顶层head随机更新中间层的hidden state 实验结果 显存占用 毕竟模型…

openstack云计算(一)————openstack安装教程,创建空白虚拟机,虚拟机的环境准备

1、创建空白虚拟机 需要注意的步骤会截图一下&#xff0c;其它的基本都是下一步&#xff0c;默认的即可 ----------------------------------------------------------- 2、在所建的空白虚拟机上安装CentOS 7操作系统 &#xff08;1&#xff09;、在安装CentOS 7的启动界面中…

RuoYi-Vue若依框架-集成mybatis-plus报错Unknown column ‘search_value‘ in ‘field list‘

报错信息 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column search_value in field list ### The error may exist in com/ruoyi/sales/mapper/ZcSpecificationsMapper.java (best guess) ### The error may involve defaultParameter…

【简单讲解下WebSocket】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Python卷积网络车牌识别系统(V2.0)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

基于单片机的无线红外报警系统

**单片机设计介绍&#xff0c;基于单片机的无线红外报警系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的无线红外报警系统是一种结合了单片机控制技术和无线红外传感技术的安防系统。该系统通过无线红外传感器实…

SpringBoot -- 外部化配置

我们如果要对普通程序的jar包更改配置&#xff0c;那么我们需要对jar包解压&#xff0c;并在其中的配置文件中更改配置参数&#xff0c;然后再打包并重新运行。可以看到过程比较繁琐&#xff0c;SpringBoot也注意到了这个问题&#xff0c;其可以通过外部配置文件更新配置。 我…

第18章 JDK8-17新特性

1. Java版本迭代概述 1.1 发布特点&#xff08;小步快跑&#xff0c;快速迭代&#xff09; 发行版本发行时间备注Java 1.01996.01.23Sun公司发布了Java的第一个开发工具包Java 5.02004.09.30①版本号从1.4直接更新至5.0&#xff1b;②平台更名为JavaSE、JavaEE、JavaMEJava 8…

复杂度的讲解

1.算法效率 如何衡量一个算法的好坏&#xff1f;从两个维度&#xff0c;时间和空间&#xff08;算法运行的快慢&#xff0c;消耗的空间大不大&#xff09;。因为计算机硬件领域的高速发展&#xff0c;如今计算机的存储量已经达到了一个很高的程度&#xff0c;所以现在我们一般…

微信公众号如何开通留言功能?

首先&#xff0c;我们需要了解为什么现在注册的公众号没有留言功能。这是因为所有在2018年之后注册的微信公众号都无法再自带留言功能。这一变化是根据微信的通知而实施的。自2018年2月12日起&#xff0c;微信对新注册的公众号进行了调整&#xff0c;取消了留言功能。这一决策主…

MySQL - 基础二

6、表的增删改查 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 6.1、Create 语法&#xff1a; INSERT [INTO] table_name[(column [, column] ...)]VALUES (value_list) [, (value_list)] ...value_list: v…

第十四届省赛大学B组(C/C++)子串简写

原题链接&#xff1a;子串简写 程序猿圈子里正在流行一种很新的简写方法&#xff1a; 对于一个字符串&#xff0c;只保留首尾字符&#xff0c;将首尾字符之间的所有字符用这部分的长度代替。 例如 internationalization 简写成 i18n&#xff0c;Kubernetes 简写成 K8s&#…

【SaaS,PaaS? XaaS -微参考】

介绍 以下是关于各种云服务模式的简要介绍&#xff0c;包括全称、定义、典型场景和应用&#xff1a; 缩写全称定义关键词典型场景和应用SaaSSoftware as a Service将软件以服务的形式交付给用户&#xff0c;用户通过互联网访问软件。提供软件电子邮件、在线办公套件&#xff…

JAVAEE——文件IO之文件操作

文章目录 文件的创建和销毁File概述构造方法常用的方法getAbsolutePath()exists()isDirectory()isFile()createNewFile()delete()deleteOnExit()list()listFiles()mkdir() 文件的创建和销毁 上面我们介绍了文件的读写操作那么文件的创建等的操作如何进行呢&#xff1f;这个操作…

前视声呐目标识别定位(四)-代码解析之启动识别模块

前视声呐目标识别定位&#xff08;一&#xff09;-基础知识 前视声呐目标识别定位&#xff08;二&#xff09;-目标识别定位模块 前视声呐目标识别定位&#xff08;三&#xff09;-部署至机器人 前视声呐目标识别定位&#xff08;四&#xff09;-代码解析之启动识别模块 …

C语言之分支语句和循环语句

前言 一、什么是语句&#xff1f; 二、分支语句&#xff08;选择结构&#xff09; 2.1 if语句 2.2 switch语句 三、循环语句 3.1 while循环 3.2 break与continue语句 3.3 getchar()与putchar() 3.3.1 缓冲区 3.4 for循环 3.4.1 一些for循环的变种 3.5 do...while循…

C语言中的结构体:高级特性与扩展应用

前言 结构体在C语言中的应用不仅限于基本的定义和使用&#xff0c;还包含一些高级特性和扩展应用&#xff0c;这些特性和应用使得结构体在编程中发挥着更加重要的作用。 一、位字段&#xff08;Bit-fields&#xff09; 在结构体中&#xff0c;我们可以使用位字段来定义成员…