从判断质数说起

从判断质数说起

以下定义能帮您更好理解本文:

0. 本文没有具体提到的数均为正整数(包括因数等)

1. 质数=素数=prime:除1与它本身,没有其他因数。

2. 开方=开平方=sqrt=square root

3. 本文如果没有明确说明,需要判断的质数的变量名均为n

第一章:朴素判断法

1.1 定义判断法

让我们来回顾下质数的定义

除1与它本身,没有其他因数的数,叫做质数

那么,我们就得出了定义判断法:

i循环[2,n-1],判断是否存在i,使得n能被i整除。

显然,这是一个正确的算法,时间复杂度 O(n)

1.2 改进

然而我们发现,我们需要更高效的算法,于是,我们有了折半定义判断法:

明显地,i不需要做那么多次循环,只需要循环到[2,n/2]即可。

显然,这个算法是正确的,时间复杂度O(n/2)相当于O(n)级别的,但是范围能显著增加

1.3 再次改进

那么,是否还有更为高效的做法呢?

答案是有的:我们有了开方判断法:

明显低,1.2中,i还是做了很多无用功,实际上只需要循环到[2,sqrt(n)]即可,这个优化,大大缩小了数量规模

为什么呢?

如果n为合数,那么设ab=n,且a>=sqrt(n),b<=sqrt(n),那么b肯定先被查找到,那么已经判断出来了合数,即可。

显然,时间复杂度O(sqrt(n)),能应付基本的判断质数了

第二章:筛法

2.1 埃斯托斯特尼筛法

具体做法是:给出要筛数值的范围sqrt(n),找出sqrt(n)以内的素数p1,p2,p3,......,pk。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个素数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个素数5筛,把5留下,把5的倍数剔除掉;不断重复下去......。

因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛法”,简称“筛法”。

大概就是这样吧,不懂的可以百度/google一下,判断n个数,时间复杂度O(nloglogn)

看起来挺好的了,但是还有更好的!

2.2 欧拉筛法

Eratosthenes筛法名字虽然高贵冷艳,但是并不难理解,原理就不多说了,但是它做了许多无用功,一个数会被筛到好几次,最后的时间复杂度是O(nloglogn),不要以为这个复杂度已经很好了,因为有直接O(n)的欧拉筛法存在,下面简单叙述一下其原理,最后由程序的运行结果来说明两者的差距。

欧拉筛法的思想就是不做无用功,原本Eratosthenes筛法的第一重循环是用来找素数,然后把素数的倍数标记,而欧拉筛法换了一个角度,第一位是找素数没有问题,但是标记的时候用的是所有数(合数素数都能用来做标记)来标记,并加上了一句特判来跳出循环,什么意思呢?对于当前的一个数i,欧拉筛法把从2, 3, 5....到小于 i 的最大素数分别和 i 相乘得到的数标记成合数。并且过程中一旦发现 i % (p[j]) == 0,则跳出循环,有什么用呢?这样做保证了每个合数只被他的最小素因子筛到一次,为什么?这么想,我们每次想要标记的数是 i * p[j], 有因子p[j], 如果 i 没有因子 p[j] 则标记(这是第一次用p[j]标记的时候干的事),易于发现当 i 中 p[j] 的指数为x时,i 是被 (i / p[j]) 这个数 * p[j] 时标记的,只标记了一次。

下面是两者对比的代码,网上看到说由于欧拉筛法的特判有取模运算,所以在数据小的时候不如Eratosthenes筛法快,亲测了一下,根本感觉不到差距,反而是数据变大以后,两者差距变得越来越明显,从消耗的时间上可以看出。(当然我在其中加了求欧拉函数的操作)。欧拉筛法的思想很巧妙,特别是应用在求一些积性函数的时候会比普通筛法更快,比如欧拉函数。

——Lerence1201

时间复杂度O(kn),k为常数,很小,几乎忽略,线性时间算法。

第三章:最终章

米勒拉宾质数检验

首先,让我们来看看跟素数有关的费马定理

如果 p 是素数,则对于所有整数 aa p ≡ a (mod p)。

根据上述的费马定理,每当 p 是素数以及 a 不是 p 的倍数时,我们有 - 1 ≡ 1 (mod p) 。而且有有效的方法计算 - 1 mod n ,且只需要 O(log n) 个模 n 乘法运算。因此我们可以确定,当这个关系不成立时,n 不是素数。对于一个给定的数的非素性来说,费马定理是一个强有力的检验。当 n 不是素数时,总是有可能来求 a < n 的一个值,使得 - 1 ≠ 1 (mod n) 。事实上,经验证明,这样一个值几乎总能非常快地求出。有某些稀少的 n 值,它们经常使得 a n - 1 ≡ 1 (mod n) ,但在此情况下,n 有小于 1/3 的因子。

我没有找到确定一个很大的数是否素数的有效的算法。但是 Miller-Rabin primatlity test 算法能够以很高的概率来检验一个很大的数是否素数。

具体可google一下,时间复杂度O(n),能够非常快地判断出是否为质数,但有一定概率,为3/4判断对,2147483647内,如果选2、5、7,则都可以判断出来。

时间: 2024-10-12 18:09:14

从判断质数说起的相关文章

判断质数的几种方法

根据维基百科定义,质数(Prime number),又称素数,指在大于1的自然数中,除了1和此整数自身外,无法被其他自然数整除的数(也可定义为只有1和本身两个因数的数).比1大但不是素数的数称为合数.1和0既非素数也非合数.质数在公钥加密算法(如RSA)中有重要的地位. 下边将会介绍几种较为常见的判断质/素数的方法: 1. 法一:最直接也最笨的方法 法一是按照质数的定义来考虑的,具体程序见下: 1 //*********************************** method 1 **

转化为用欧几里得算法判断互质的问题D - Wolf and Rabbit

Description There is a hill with n holes around. The holes are signed from 0 to n-1. A rabbit must hide in one of the holes. A wolf searches the rabbit in anticlockwise order. The first hole he get into is the one signed with 0. Then he will get into

1028. 判断互质

1028. 判断互质 (Standard IO) 时间限制: 1000 ms  空间限制: 262144 KB  具体限制 题目描述 输入两个正整数m和n,判断m和n是否互质(即最大公约数为1),是则输出Yes,否则输出No. 输入 输入两个整数m和n,中间用空格隔开. 输出 如互质输出Yes,否则输出No. 样例输入 36 56 样例输出 No 数据范围限制 1<=n,m<2^31 1 #include<cstdio> 2 using namespace std; 3 long

判断一个数的质因子个数

#include<iostream> using namespace std; int Prim( int n) { int i=2,cnt=0; while(n>0&&n>=i) { if(n%i==0) { cnt++; while(n%i==0) { n=n/i; } } i++; } return cnt; } int main() { int n; while(cin>>n) { cout<<Prim(n)<<endl;

判断2个正整数是否互质

1.   Two positive integers i and j are considered to be co-prime if there exists no integer greater than 1 that divides them both.  Write a function co-prime that has two input parameters, i and j, and returns a value of 1 for true if i and j are co-

POJ 1811 大素数判断

数据范围很大,用米勒罗宾测试和Pollard_Rho法可以分解大数. 模板在代码中 O.O #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; __int64 pri[]= {2,3,5,7,11,13,17,19,23,29,31};//用小素数表做随机种子避免第一类卡米

容斥原理 求M以内有多少个跟N是互质的

开始系统的学习容斥原理!通常我们求1-n中与n互质的数的个数都是用欧拉函数! 但如果n比较大或者是求1-m中与n互质的数的个数等等问题,要想时间效率高的话还是用容斥原理! 本题是求[a,b]中与n互质的数的个数,可以转换成求[1,b]中与n互质的数个数减去[1,a-1]与n互质的数的个数. #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define LL long

解模线性方程组 非互质中国剩余定理

首先咱们得感谢KIDx大神给出这样的解法. 这里是我所学习这个算法的地方:http://972169909-qq-com.iteye.com/blog/1266328 . 我将对这个算法进行一定的总结与梳理,以及小地方的修正. 今有物不知其数,三三数之余二:五五数之余三:七七数之余二.问物几何? 这是经典的孙子定理.我们注意到其中的模数都是互质的,这样可以让我们进行传统孙子定理中的转化与合并. 但是如果遇到不是互质的模线性方程组我们要怎么办呢? [主要使用手段:合并方程] 利用一定手段,不断的合

POJ1811 Prime Test(判断随机素数)

题意:给出一个N(2 <= N < 2^54),如果是素数,输出"Prime",否则输出最小的素因子 膜拜斌巨 #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <cmath> #include <stdlib.h> #include <