蒟蒻君的数学学习之路2——质数相关算法
Posted 蒟蒻一枚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蒟蒻君的数学学习之路2——质数相关算法相关的知识,希望对你有一定的参考价值。
⭐前言
质数,是数学里很重要的东东。若
p
p
p为质数,
p
p
p为
>
1
>1
>1的整数且
p
p
p有且仅有
1
1
1和
p
p
p两个因数。
今天,蒟蒻君将和大家一起学习质数相关算法(难度递增qwq)。
文章目录
⭐一、质数判定
🎉 1.1 1.1 1.1 试除法
🚀思路
最常用的算法。
- 假设 n n n不是质数,则必有 a , b a,b a,b使得 n = a × b n = a \\times b n=a×b;
- 令 a < b a < b a<b, 则 a ≤ n a \\le \\sqrt n a≤n;
- 枚举 a = 1 − n a = 1 - \\sqrt n a=1−n,若所有 a a a均不被 n n n整除,则 n n n为质数,否则为合数。
- 注意特判 0 0 0和 1 1 1。
时间复杂度:
O
(
n
)
O(\\sqrt n)
O(n);
空间复杂度:
O
(
1
)
O(1)
O(1)。
🚀代码
inline bool isprime(int n)
if (n < 2)
return false;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0)
return false;
return true;
🎉 1.2 1.2 1.2 卡常写法
🚀思路
在法一的基础上可以进行以下优化:
若
n
n
n为质数,则
n
m
o
d
2
≠
0
n \\mod 2 \\neq 0
nmod2=0且
n
m
o
d
3
≠
0
n \\mod 3 \\neq 0
nmod3=0,则
n
m
o
d
6
=
1
/
5
n \\mod 6 = 1/5
nmod6=1/5。跳过
2
−
4
2 - 4
2−4,时间复杂度可提高到之前的
1
3
\\frac13
31。
注意特判
n
=
2
/
3
/
5
/
7
/
11
n=2/3/5/7/11
n=2/3/5/7/11还有
n
=
2
/
3
/
5
k
(
k
∈
N
)
n=2/3/5k(k\\in N)
n=2/3/5k(k∈N)。
时间复杂度:
O
(
n
)
O(\\sqrt n)
O(n),只是常数有些变化;
空间复杂度:
O
(
1
)
O(1)
O(1)。
🚀代码
inline bool isprime(int n)
if (n < 2)
return false;
if (n == 2 || n == 3 || n == 5 || n == 7 || n == 11)
return true;
if (n % 2 == 0 || n % 3 == 0 || n % 5 == 0)
return false;
for (int i = 1; i <= n / 6 + 1; ++i) // 枚举n = 6 * i +/- 1
if (i * 6 >= sqrt(n) + 5)
break;
if ((n % (i * 6 + 1) == 0) || (n % (i * 6 + 5) == 0))
return false;
return true;
如果让你从
1
−
100
1 - 100
1−100这些数里筛出质数,那你还会一个一个数地试除吗 (当然你没有背过)?
质数筛法适用于先预处理,然后多次查询的条件下。
下面我们来学习质数的两种筛法叭~
注意,质数筛法标程以洛谷P3383【模板】线性筛素数为例。
🎉 1.3 1.3 1.3 埃氏筛法
🚀思路
相信大家也都对这种方法不陌生。
比如我们要判断
1
−
100
1 - 100
1−100中选出所有质数,那么我们可以这样做:
- 先将 1 − 100 1 - 100 1−100写在纸上。
- 我们在 2 2 2上画一个小圈圈,然后叉掉所有 2 2 2的倍数;
- 再在 3 3 3上画一个小圈圈,删掉所有 3 3 3的倍数;
- 现在你发现 4 4 4已经被删掉了,那么就可以在 5 5 5上画一个圈圈,然后删掉所有 5 5 5的倍数。
- 以此类推,直到 1 − 100 1 - 100 1−100中所有数都被划掉或圈起为止,质数为所有被圈出来的数。
接下来我们来分析一下ta的时间复杂度。
因为所有数要么都被删除或圈出一次,则时间复杂度为
O
(
n
)
O(n)
O(n)。
nonono
仔细思考可知,有些数会被删除多次,如
6
6
6被
2
2
2和
3
3
3删除,则:
T
(
n
)
=
O
(
∑
p
≤
n
n
p
)
=
O
(
∑
p
≤
n
1
p
)
=
O
(
n
l
o
g
l
o
g
n
)
T(n)=O(\\displaystyle \\sum_p \\le n \\fracnp)=O(\\displaystyle \\sum_p \\le n \\frac1p)=O(nloglogn)
T(n)=O(p≤n∑pn)=O(p≤n∑p1)=O(nloglogn);
时间复杂度:
O
(
n
l
o
g
l
o
g
n
)
O(nloglogn)
O(nloglogn);
空间复杂度:
O
(
n
)
O(n)
O(n)。
🚀代码
注意:此方法时间复杂度较高,需使用scanf/printf/ios :: sync_with_stdio(0)方可AC。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e8 + 5;
bool vis[N];
int p[N], cnt;
void init(int n)
vis[1] = true;
for (int i = 2; i <= n; ++i)
if (vis[i])
continue;
p[++cnt] = i;
for (long long j = 1ll * i * i; j <= n; j += i)
vis[j] = true;
int main()
int n, q;
scanf("%d %d", &n, &q);
init(n);
while (q--手撕STL——队列的内部实现