【数学】质数、合数、筛质数、分解质因数
-
质数和合数是针对所有大于 1 的 “自然数” 来定义的(所有小于等于1的数都不是质数)。
-
所有小于等于 1 的整数既不是质数也不是合数.
-
质数的判定——试除法
-
代表的含义是 能整除 ,(这里的 代表整除)
-
一个合数的约数总是成对出现的,如果 ,那么 ,因此我们判断一个数是否为质数的时候,只需要判断较小的那一个数能否整除 就行了,即只需枚举 ,即
-
这个函数执行的时候比较慢.
一般这样写:
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;
}
- 分解质因数——试除法(算数基本定理)
任何一个大于1的自然数 ,如果N不为质数,都可以唯一分解成有限个质数的乘积
,这里 且均为质数,其诸指数是正整数。
这样的分解称为的标准分解式。
- 特别要注意——分解质因数与质因数不一样,分解质因数是一个过程,而质因数是一个数.
- 一个合数分解而成的质因数最多只包含一个大于 sqrt(n)sqrt(n) 的质因数(反证法,若 nn 可以被分解成两个大于 sqrt(n)sqrt(n) 的质因数,则这两个质因数相乘的结果大于 nn ,与事实矛盾)
- 质因子(质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序的情况下,每个正整数都能够以唯一的方式表示成它的质因数的乘积。
- 两个没有共同质因子的正整数称为互质。因为 11 没有质因子,11 与任何正整数(包括 11 本身)都是互质。
- 只有一个质因子的正整数为质数。
- 当枚举到某一个数 的时候, 的因子里面已经不包含 里面的数(已经被除干净了),如果 ,则 的因子里面也已经不包含 里面的数,因此每次枚举的数都是质数。
void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
if (x > 1) cout << x << ' ' << 1 << endl; // 大于sqrt(n)的数
cout << endl;
}
- 筛质数(朴素筛法)
- 步骤:把 [2,n−1][2,n−1] 中的所有的数的倍数都标记上,最后没有被标记的数就是质数.
- 原理:假定有一个数 未被 中的数标记过,那么说明,不存在 中的任何一个数的倍数是 ,也就是说 中不存在 的约数,因此,根据质数的定义可知: 是质数.
- 调和级数:当 趋近于正无穷的时候,( 是欧拉常数,约等于 0.577 左右)
- 时间复杂度:约为 (注:此处的 特指以 为底)
- 埃拉托斯特尼筛法(埃氏筛)
- 要得到自然数以内的全部素数,必须把不大于的所有素数的倍数剔除,剩下的就是素数。
- 质数定理: 中有 个质数.
- 时间复杂度:
写法一:
void get_primes(int n)
{
for(int i = 2; i <= n; i ++ )
{
if(!st[i])
{
primes[cnt ++] = i;
for(int j = 2 * i; j <= n; j += i) st[j] = true; // 埃氏筛优化,把for循环放到if外面就是朴素埃氏筛
}
}
}
写法二:
void get_primes(int n)
{
for(int i = 2; i <= n; i ++ )
{
if(!st[i]) primes[cnt ++] = i;
else continue; //埃氏筛优化
for(int j = 2 * i; j <= n; j += i) st[j] = true;
}
}
- 线性筛(欧拉筛)
- 若,线性筛和埃氏筛的时间效率差不多,若 ,线性筛会比埃氏筛快了大概一倍。
- 核心:内的合数 只会被其最小质因子筛掉。
- 原理: 之内的任何一个合数一定会被筛掉,而且筛的时候只用最小质因子来筛,然后每一个数都只有一个最小质因子,因此每个数都只会被筛一次,因此线性筛法是线性的.
- 枚举到 的最小质因子的时候就会停下来,即
if (i % primes[j] == 0) break;
- 当
i % primes[j] != 0
时,primes[j]
一定小于i
的最小质因子,primes[j]
一定是primes[j] * i
的最小质因子. - 当
i % primes[j] == 0
时,primes[j] 一定是i
的最小质因子,而primes[j]
又是primes[j]
的最小质因子,因此primes[j]
是primes[j] * i
的最小质因子.
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;
// j < cnt 不必要,因为 primes[cnt - 1] = 当前最大质数
// 如果 i 不是质数,肯定会在中间就 break 掉
// 如果 i 是质数,那么 primes[cnt - 1] = i,也保证了 j < cnt
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程