素数判定随机算法
什么是素数? 素书就是那些因素除了1就是它们自身的数们.
欧几里德早在2000多年前,就证明了素数有无穷多个.
数学领域最古老的未解之迷是和素数, 加法相关.
其中一个就是孪生素数猜想-----存在无限多组差为2的素数对.
另外一个就是哥德巴赫猜想-----所有大于2的偶数都可以表示为两个素数之和.
切比雪夫证明过在(n, 2n)中有一个素数, 那么当n取为素数p时, 则有(p, 2p)中有一个素数q, 即0< q-p <p.那么当p任意增加时, q-p可能是任意大.
陈景润做出的结果是在(n, n+ n^0.6)之间存在着素数. 同理0< q-p <p^0.6
现在有个猜想:(n^2, (n+1)^2)之间存在素数.
上个月, 华人张益堂解决了据说是孪生素数猜想里程碑式的问题就是, 数学家们还是不能排除素数的间隔会一直增长最终超过一个特定上限的可能. 之前陈景润做出的结果是在张解决了这个问题,他证明了 对于某一个小于7千万的数字N,存在无穷多的素数对,他们之间的差小于N。当某人把7千万强化到3时, 孪生素数猜想是否正确就可以证明了.
素数判定: 给定一个正整数n, 判断n是否为素数
确定性算法
算法思想:用2, ..., sqrt(n)来整除n, 若存在一个数能整除n, 则判定n为合数; 否则, n为素数.
时间复杂度:指数时间复杂度
算法实现:
import java.io.*; public class IsPrime { public static Integer IsPrime (Integer num) { if(num<=1) return 0; for(int i=2; i<=Math.sqrt(num); i++ ){ if(num%i==0) return -1; } return 1; } public static void main(String[] args) throws NumberFormatException, IOException { BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); Integer b=Integer.parseInt(buf.readLine()); System.out.println(IsPrime(b)); } }
在讲素数判定的随机算法时, 首先讲几个定理.
Fermat little theorem: 对于任意素数p, 正整数a, 同时gcd(p, a)=1,则,
即.
证明可以用数学归纳法.也可以按照下面的证明方法:
证明:设A={1, 2, 3,..., p-1}, 在A中任取一个数a,用a分别乘以A中的元素,得到B
B={a, 2a, 3a, ..., (p-1)a}
我们显然可以知道|B| = p-1. 且A和B中的每个元素都与p互素(这个可以用反证法证明).
故{1, 2, 3,..., p-1} = {a, 2a, 3a, ..., (p-1)a} (mod p)
因此,(p-1)! = (p-1)!a^(p-1) (mod p)
显然p | (p-1)![a^(p-1)-1]
又,p不能被(p-1)!整除,所以p能被a^(p-1)-1]整除,即.
Note:费马小引理只是素数的必要条件,而不是充分条件. 因为不仅仅只有素数满足,同时合数当中的卡迈克数也满足.
例如: a^560 = 1 (mod 561)
证明: a^560 = 1 (mod 561)
我们知561 = 3 * 11 * 17,
a^2 = 1 (mod 3) => (a^2)^280 = 1 (mod 3) => 3 | a^560 - 1.
a^10 = 1 (mod 11) => (a^10)^56 = 1 (mod 3) => 11 | a^560 - 1.
a^16 = 1 (mod 17) => (a^16)^35 = 1 (mod 3) => 17 | a^560 - 1.
故561 | a^560 -1 (mod 3)
可以基于Fermat little theorem来写一个随机算法, 来判断n是否为素数.
算法思想: 随机的选择10个数, a_1, a_2, ..., a_10,其中2=<a_i<=n,然后:
(0)计算n=2, 若是,则prime number.否则,计算gcd(n, 2), 若等于0, 则为composite number, 结束;否则(1).
(1)gcd(n, a_i)>1, 若是,则为composite number; 否则(2).
(2)判断a_i^(n-1)=1 (mod n), 若成立, 则(3); 否则为composite number,结束.
(3)此时,n必定是奇数,所以(n-1)为偶数. a_i^(n-1)-1=0 (mod n) => [a_i^(n-1/2)-1][a_i^(n-1/2)-1]=0 (mod n);
最终有a_i^(n-1/2) = +1或-1. 基于上述,a_i^(n-1 / 2)若不是为1或-1, 则是composite number, 结束;否则(4)
(4)若全部为1, 则输出 composite number, 结束;否则(5). --------------------[补充:此处可以换成欧拉准则,结果会更精确]
这一步,问了一下其他同学, 就是保证双边错误,并且减小出错的概率.
(5)输出prime number.
BPP(Bounded error, Probabilistic, polynomial time), 在最坏情况下,
(1) x属于L, Pr[A(x) accepts] >=2/3;
(2)x不属于L, Pr[A(x) doesn't accepts] >=2/3.
证明: 上述算法是BPP算法.
(1)当n为prime number时, 记出错事件为A, 同时由上述算法可以看出, 可能且仅能出错的地方在步骤(4);
出错概率Pr(A)=(1/2)^10 <=1/3.
(2)当n为composite number时, 记出错事件为B, 则出错的概率在第(5)步.
则出错概率Pr(B)<=Pr(a^(i-1 / 2)=1或-1)^10<=(1/2)^10 < 1/3
由(1)(2)得证, 上述算法属于BPP.