素数检验法

原创 2007年09月18日 13:11:00
 数的素性检验方法问题在近几年得到了飞速的发展,过去,要检验一个数 n 是否是素数,最简单的方法是用试除法,用小于n的平方根以下的所有素数去除n,若都除不尽,则n就是素数,否则为合数.这对于比较小的数来说还适用,若用计算机编成程序,对于10位数,几乎瞬间即可完成,对于一个20位数,则需要2个小时,对于一个50位数就需要一百亿年,令人吃惊的是,要检验一个一百位数,需要的时间就猛增到10^36年.到了1980年,这种困难的情况得到了改观,阿德曼(Adleman),鲁梅利(Rumely),科恩(Cohen),和伦斯特拉(Lenstra)研究出一种非常复杂的技巧,现在以他们的名字的首字母命名的ARCL检验法,检验一个20位数只消10秒钟,对于一个50位数用15秒钟,100位数用40秒钟,如果要他检验一个1000位数,只要用一个星期也就够了.但是大部分的素性检验法都不能分解出因数来,只能回答一个数是否是素数.
       我们知道,费马小定理是现代素数判定方法的基础,如果该定理的逆命题成立那该多好,只要计算一下ap-a是否能被p整除,能则p是素数,否则p是和数.遗憾的是这只对1<p<341内的数成立,因为2341-2能被合数341整除,即费马小定理的逆命题不成立.前面已经说过像341这样的数叫做伪素数.
    ARCL检验法改进了费马检验,它不再受伪素数的愚弄.这种检验法需要相当多的高深的数学知识.现在我还不能提供这个方法的详细情况,以后可能会的.在下面我将要讲的是n-1检验法和n+1检验法.
    1.n-1 检验法
如果对于奇数 n,我们已经知道了n-1的素因子分解式,那么如下的n-1检验法将是有效的.在1891年,E.卢卡斯将费马小定理改进成对于检验素数很实用的形式,后来又由克拉奇科和莱默进一步改进:

定理一:设n>1是一个奇数,如果对于n-1的每一个素因子q存在一个整数a使得:


           an-1 = 1 (mod n), and

           a(n-1)/q ≠ 1 (mod n);

则n是素数.

这个定理的不足之处是需要知道n-1的全部因子,那么能不能不需要如此呢?下面一个定理是泊克林顿(Pocklingdon)在1914年发现的:

泊克林顿定理:设n-1=qkR,这里q是素数,并且R不能被q整除.如果存在一个整数a使得an-1=1并且
gcd(a(n-1)/q-1,n) = 1,则n的每一个素因子q都具有qkr+1的形式.

利用这个定理,我们可以将定理一改进如下:

定理二:假定 n-1 = FR, 这里 F>R, gcd(F,R)=1 并且已知 F的素因子分解.如果对于F的每一个素因子q 都存在一个整数a >1 使得
           an-1 = 1 (mod n)
           gcd(a(n-1)/q-1,n) = 1;
则 n 是素数. (注意对每一个 q 都可以用不同的 a).

定理二还可以进一步改进如下:如果 F<R, 并且R 的每一个因子都大于sqrt(R/F); 或者 n<2F3, R=rF+s, 0<s<F, 这里 r 是一个奇数或者 s2-4r 不是一个平方数;则 n 是素数.

    在我们转向另一种检验法之前,让我们把如下定理二的两种应用记述如下:
佩班(Pepin)检验法(1877): 让 F(n) 第n个费马数 ( F(n) = 22n+1) 并且 n>1.

           F(n) 是素数当且仅当
           3(F(n)-1)/2 = -1 (mod F(n)).

普罗斯(Proth)定理 (1878): 让 n = h.2k+1且 2k > h. 如果存在一个整数a使得:
a(n-1)/2 = -1 (mod n), 则 n 是素数. (这个定理已经有一个程序,欢迎下载)

定理三 : 让 n = h.qk+1 且 q 是素数 并且 qk > h. 如果存在一个整数a使得 an-1 = 1 (mod n), 并且 gcd(a(n-1)/q-1,n) = 1, 则 n 是素数.

 

    2. n+1 检验法和Lucas-Lehmer检验法

    有许多已知的大素数具有形式N-1, 而 N 是很容易分解因数的,为什么这些形式的数能被检验呢?因为对它们可以应用一种类似于费马小定理的有趣定理来对付它们.
  
    假定我们选择两个整数 p 和 q 使得 p2-4q 不是模 n的一个平方剩余, 则多项式 x2-px+q 有两个不同的根, 其中之一是 r = (p+sqrt(p2-4q))/2, 并且很容易推导出 r 的幂具有如下形式:

引理 1: rm = (V(m) + U(m)sqrt(p2-4q))/2

这里 U 和 V 分别定义如下:

U(0) = 0, U(1) = 1, U(m) = pU(m-1) - qU(m-2)

V(0) = 2, V(1) = p, V(m) = pV(m-1) - qV(m-2)

这就是关于 p 和 q的卢卡斯序列. 一个众所周知的特例是令 p=1, q=-1, 则 U(m) 斐波拿契数列.卢卡斯序列有许多特性,使得它们能很快地进行计算(用一种类似于我们在计算 xm 时所用的重复平方的方法):

          U(2m) = U(m)V(m)

          V(2m) = V(m)2-2qm

现在我们来叙述这种类似于费马小定理的定理:

引理 2: p, q 和 r 同上 (使得 p2-4q 不是模 n的一个平方剩余),
       让 2r = a+bsqrt(p2-4q) (mod n) .
       如果 n 素数, 则 2rn = a-bsqrt(p2-4q) (mod n).

这样说有点太混乱, 让我们用我们的 U 序列(即sqrt(p2-4q)的系数). 

引理 3: (p, q 同上) 如果 n 是素数, 则 U(n+1) = 0 (mod n).

现在我们可以重新叙述一下定理了:

定理 4: 让 n > 1 是一个奇整数. 如果对于 n+1 的每一个素因子 r 都存在相应的素数 p 和 q (这里 p2-4q 不是 n 的平方剩余)使得:

U(n+1) = 0 (mod n),并且

U((n+1)/r) is not 0 (mod n);

则 n 是素数.(确定一个数 d 是否是 modulo n 的一个平方剩余很容易用 Jacobi 符号来决定,这在任何一本数论书中都可以找到.)
    一个重要的有趣特例是设S(k) = V(2k+1)/22k

卢卡斯-莱默检验法(1930): 让 M(n) 是第 n 个梅森素数 (即 M(n) = 2n-1). M(n) 是素数当且仅当    S(n-2) = 0 (mod M(n)) 这里 S(0) = 4 并且 S(k+1) = S(k)2-2.

这个检验法计算特别快,因为它不需要做乘法,只要做移位即可.编写程序也很容易.

CODE【VS】2849 素数判定 3(米勒拉宾素数测试的方法)

题目描述 Description 输入一个正整数x(3 输入描述 Input Description 一行一个正整数 输出描述 Output Descr...
  • Aiwen1413
  • Aiwen1413
  • 2017年04月17日 10:23
  • 164

素数打表的四种解法

题目:给出一个正整数n,打印出所有从1~n的素数(即质数);   1.傻瓜解法 复制代码   int i,n; while(scanf("%d",&n)!=EOF) { ...
  • gtuif
  • gtuif
  • 2017年06月26日 08:34
  • 349

算法之素数筛法

方法一 //判断是否是一个素数 int IsPrime(int a){ //0,1,负数都是非素数 if(a ...
  • SJF0115
  • SJF0115
  • 2013年03月20日 09:08
  • 7881

筛选法求素数改进

以前稍微总结了下求素数的办法。但是无奈效率都不高。 今天逛了很多关于求素数的博客,于是总结了一下最终写出了一个筛选法的改进算法。 筛选法: (一般筛选法)这种方法比较好理解,初始时,假设全部都...
  • slime_kirito
  • slime_kirito
  • 2015年06月15日 22:24
  • 363

素数筛选法 (求1~n的素数)

具体方法就不阐述了,百度一下就能找到,
  • yzj577
  • yzj577
  • 2014年07月26日 18:03
  • 4400

筛选法求素数 java

思路:在一个boolean类型的数组中 ,从第二个开始遍历,将2的倍数置为false,3的倍数置为false。实例说明一下: 求0-10的素数,定义数组boolean b[]=boolean[11]...
  • jtracydy
  • jtracydy
  • 2016年09月13日 10:44
  • 1389

【算法】普通方法和筛选法求素数

素数指的是因子只有1和本身的数(1不是素数),求解素数在数学上应用非常广泛,而求解n以内的素数也是我们编程时常遇到的问题,在这个问题上,筛选法求解素数运行得非常快。下面首先介绍如何判断一个是不是素数,...
  • zgljl2012
  • zgljl2012
  • 2015年04月02日 00:09
  • 3529

打表法判断素数

方法一:普通法 int isprime(int x) { int logo = 0, i, m; if (x==2 || x==3) logo = 1; els...
  • DaiHaoC83E15
  • DaiHaoC83E15
  • 2014年02月06日 14:37
  • 1092

ACM基础知识储备-快速筛法求素数

求素数是程序设计比赛中经常遇到的问题,最基本的方法是通过素数的定义直接判断,只能被1和它本身整除的数就是素数了。这种方法适合判断单个数是否为素数,当要求一个范围内素数而这个范围又比较大时,这种方法就不...
  • stack_queue
  • stack_queue
  • 2016年12月10日 20:46
  • 1695

素数筛法及其优化

今天试了一下素数筛法 要求1-100000范围内的素数,如果用自定义函数挨个求,对于大范围的求素数会非常耗时。复杂度为O(n * sqrt(n)),所以可以用素数筛法来求大范围内的素数 说一下原理...
  • sdutstudent
  • sdutstudent
  • 2016年12月21日 12:34
  • 341
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:素数检验法
举报原因:
原因补充:

(最多只允许输入30个字)