质数浅谈
这篇博文讲的只是质数入门级的东西.
OI数论的开始,就是素数.
素数的一些性质成为OI出题的热点,于是我们不得不学习令人心烦的数论.
定义
众所周知
若一个正整数无法被除了
1 和它自身之外的任何自然数整除,则称该数为质数(prime number,又称素数),否则称该数为合数(composite number).特别的,
1 既不是质数,也不是合数.由定义,
2 是最小的质数,也是唯一的偶质数.
为了方便描述,在本文中,有时会用
一、质数相关定理
然而并没有什么用QwQ.
质数无穷定理
我也不知道它叫什么,随便起了个名字qwq.
质数的个数是无限的.
读者自证不难.可以参考《几何原本》中的证明.
质数分布定理
预警:这一方面笔者不能写出很严谨的说明
在自然数集合中,质数分布较为稀疏.
对正实数
x ,定义\pi(x) 为不大于x 的质数的个数,有:\pi(x)\approx \frac{x}{\ln x} 推论1 :从不大于
n 的自然数随机选一个,它是素数的概率约为\frac{1}{\ln n} .推论2 :第
n 个质数的渐进估计为n \ln n .
二、质数的判定
问题
给定一个大于
1 的正整数N ,判定其是否为质数.
试除法 及其常数优化
引理一
若一个正整数
N 为合数,则[2,\,\sqrt{N}] 中存在整数i ,使得i\mid N .
证明: 显然
由合数定义,必定存在正整数
j 满足j\mid N,\,j\in [2,\,N-1] ;假设原命题不成立,则
j\in[\sqrt{N}+1,\,N-1] ;而由于j\mid N ,显然,它们的比i=\frac{N}{j} 也满足i\mid N ,且i\in[2,\,\sqrt{N}] ;这与假设矛盾.故假设不成立,原命题成立.证毕.
算法思想
由引理一,我们只需要扫描
C++ code
bool if_prime (int n) {
if (n == 1) return false;
for (int i = 2, i * i <= n; ++i)
if (!(n % i)) return false;
return true;
}
试除法的时间复杂度为
引理二
\forall p\in\complement_{\{2,3\}}\mathbb{P},\,p\in\{x\mid x=6k\pm1,\,k\in\mathbb{N_+}\}
证明:
显然,形如
6k 、6k+2 、6k+3 、6k+4 (k\in\mathbb{N} )的自然数均能为2 或3 整除.由此,除
2 和3 本身外的所有质数,只可能为6k\pm1\,(k\in\mathbb{N_+}) 的样式.
思想
由引理二,我们只需特判
C++ code
bool if_prime (int n) {
if (n == 1) return false;
if (n == 2 || n == 3) return true;
if (n % 6 != 1 && n % 6 != 5) return false;
for (int i = 5, i * i <= n; i += 6)
if (!(n % i && n % (i + 2))) return false;
return true;
}
时间复杂度降至
有一些效率更高的随机性算法(例如 Miller-Robbin),有较小的概率把合数判定为质数,但多次判定合起来的错误概率趋近于零,但超出了我们的讨论范围 (其实是我还没有熟练掌握),在此只捎带一提.
三、质数的筛选
问题:
给定正整数
N ,求出[1,\,N] 中的所有质数.
Eratosthenes 筛选法
出于显而易见的原因, 通常被称为埃氏筛.
Eratosthenes(BC276-BC194),希腊
哲学家、数学家,约 BC240 计算地球的直径误差小于2\% ,为当时世界最早最准确(逐渐偏离主题).
算法思想
由质数定义可知,任一整数
我们从
如果还不能理解,就摆出这幅著名的动图.
参照上图,在标记的过程中,
C++ code
int m, p[M]; // m for number of primes
bool vis[N];
void primes (int n) {
// memset (vis, 0x00, sizeof vis), m = 0;
vis[1] = true;
for (int i = 2; i <= n; ++i)
if (!vis[i]) {
p[++m] = i;
for (int j = i * i; j <= n; j += i)
vis[j] = true;
}
}
Eratosthenes 筛选法的时间复杂度为 (不要问我这个等号怎么推出来的,我也不知道),实现简单且效率接近线性,是很常用的质数筛法.
线性筛法
似乎也被称为欧拉筛吧,这个名字有什么依据我就不知道了.
Eratosthenes 筛选法 浪费的时间
标记一个数
检查 Eratosthenes 筛选法,我们在标记
对于一个合数
算法思想
筛出一个质数
相反,如果我们把
如果仍感到理解困难,请读者参照下面的代码模拟一两次.
C++ code
int m, p[M];
bool vis[N];
void primes (int n) {
// memset (vis, 0x00, sizeof vis), m = 0;
vis[1] = true;
for (int j = 2; j <= n; ++j) {
if (!vis[j]) p[++m] = j;
for (int i = 1; i <= m && p[i] * j <= n; ++i) {
vis[p[i] * j] = true;
if (!(j % p[i])) break;
}
}
}
每个合数
四、质因数分解
算数基本定理
一称唯一分解定理
任一大于
1 的正整数N 的正整数可被唯一分解为有限个质数的成绩,写作:N=\prod_{1\le i\le m}{p_i}^{c_i}\quad(c_i\in\mathbb{N^* },\,p_i\in\mathbb{P},\,p_1<p_2<\cdots<p_m) 其中,
\prod_{i=1}^{m}{p_i}^{c_i} 称为N 的标准分解式.
问题
给定一个大于
1 的正整数N ,求其标准分解式.
试除法
算法思想
结合 Eratosthenes 筛选法的思想,扫描
因为一个合因子在扫描到这个合数之前必定已从
特别地,若得不到
这样就得到了
C++ code
int m, p[M], c[M];
void divide (int n) {
// m = 0;
for (int i = 2; i * i <= n; ++i)
if (!(n % i)) {
p[++m] = i;
while (!(n % i)) ++c[m];
}
if (n > 1) p[++m] = n, ++c[m];
}
易知时间复杂度为
Pollard's Rho 是一个效率更高的算法,不过明显超出了我们的讨论范围 (然而其实是我不会),在此捎带一提.
小结
本文到此结束,但显然这只是很初步的内容,以后在学习的过程中会逐渐更新新的算法和新的理解,并加上一些代表性的例题.
written by Yu-343