蒟蒻君的数学学习之路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 试除法

🚀思路

最常用的算法。

  1. 假设 n n n不是质数,则必有 a , b a,b a,b使得 n = a × b n = a \\times b n=a×b
  2. a < b a < b a<b, 则 a ≤ n a \\le \\sqrt n an
  3. 枚举 a = 1 − n a = 1 - \\sqrt n a=1n ,若所有 a a a均不被 n n n整除,则 n n n为质数,否则为合数。
  4. 注意特判 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 24,时间复杂度可提高到之前的 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(kN)

时间复杂度 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 1100这些数里筛出质数,那你还会一个一个数地试除吗 (当然你没有背过)
质数筛法适用于先预处理,然后多次查询的条件下。
下面我们来学习质数的两种筛法叭~
注意,质数筛法标程以洛谷P3383【模板】线性筛素数为例。

🎉 1.3 1.3 1.3 埃氏筛法

🚀思路

相信大家也都对这种方法不陌生。
比如我们要判断 1 − 100 1 - 100 1100中选出所有质数,那么我们可以这样做:

  1. 先将 1 − 100 1 - 100 1100写在纸上。
  2. 我们在 2 2 2上画一个小圈圈,然后叉掉所有 2 2 2的倍数;
  3. 再在 3 3 3上画一个小圈圈,删掉所有 3 3 3的倍数;
  4. 现在你发现 4 4 4已经被删掉了,那么就可以在 5 5 5上画一个圈圈,然后删掉所有 5 5 5的倍数。
  5. 以此类推,直到 1 − 100 1 - 100 1100中所有数都被划掉或圈起为止,质数为所有被圈出来的数。

接下来我们来分析一下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(pnpn)=O(pnp1)=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——队列的内部实现

算法中数学相关知识-倍数约数完全数质数最小公倍数

Java蒟蒻的学习之路——数组排序

Java蒟蒻的学习之路——StringBuffer和StringBuilder类

计蒜客习题 蒜头君的猜想(埃氏筛)

娱乐一下:汤姆君的大转盘算法(搞笑版)