PS:本人第一次写随笔,写的不好请见谅。

  接触MillerRabin算法大概是一年前,看到这个算法首先得为它的神奇之处大为赞叹,竟然可以通过几次随机数据的猜测就能判断出这数是否是素数,虽然说是有误差率,但是相对于他比其他素数判断的高效,真的是可以说是完美级。那时候忙于找工作,所以也没有细究,现在空下来终于对这个算法有了一定的理解。

  先说两个定理:

    (1) 当x<p时,满足x^(p-1) % p = 1,说明x与p互质;

    (2) 当x<p时,满足x^2 % p = 1;  x的解为 x = 1 或者 x = p -1;

  根据第一个定理,我们可以在[2,p-1)中间随机选择一个数,然后根据定理1判断是否是素数(测试准确率跟测试次数有关,多次检测)。定理2可以做二次探索。

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
#define S 10 long mod_mul(long a,long b,long n) {
long res = ;
while(b) {
if(b&)
res = (res + a) % n;
a = (a + a) % n;
b >>= ;
}
return res;
} long mod_exp(long a, long b, long n) {
long res = ;
while(b) {
if(b&)
res = mod_mul(res, a, n);
a = mod_mul(a, a, n);
b >>= ;
}
return res;
} bool miller_rabin(long n) { //过滤器
if(n == || n == || n == || n == || n == ) return true;
if(n == || !(n%) || !(n%) || !(n%) || !(n%) || !(n%)) return false; long x, pre, u;
int i, j, k = ;
u = n - ; //要求x^u % n while(!(u&)) { //如果u为偶数则u右移,用k记录移位数
k++; u >>= ;
} srand(time());
for(i = ; i < S; ++i) { //进行S次测试
x = rand()%(n-) + ; //在[2, n)中取随机数
if((x%n) == ) continue; x = mod_exp(x, u, n); //先计算(x^u) % n,
pre = x;
for(j = ; j < k; ++j) { //把移位减掉的量补上,并在这地方加上二次探测
x = mod_mul(x, x, n);
if(x == && pre != && pre != n-) return false; //二次探测定理,这里如果x = 1则pre 必须等于 1,或则 n-1否则可以判断不是素数
pre = x;
}
if(x != ) return false; //费马小定理
}
return true;
} int main()
{
for(int i=;i<;++i)
if(miller_rabin(i))
cout<<i<<" ";
return ;
}

  mod_mul与mod_exp是关于求模。不要看这两个函数很高大上,其实换种形式会更加理解。

long mod_mul(long a,long b,long n) {

    //求 (a*b)%n
//在不考虑数据上移时,先求a*b的值
long res = ; // res表示a*b的积
//举例 5(十进制) * 1101(2进制) = 5 * 2^0 + 5*0*2^1 + 5*2^2+5*2^3;
while(b) {
if(b&)
res = res + a;
a = *a;
b >>= ;
}
return res%n; //最后求模
} long mod_exp(long a, long b, long n) {
long res = ;
// res = a^b,把b分解成二进制
while(b) {
if(b&)
res = res * a;
a = a*a;
b >>= ;
}
return res%n;
}

现在讲米勒算法:

  1、n为待判定数字,先取一个数u = n - 1;

2、通过循环除二,分解成 u(原) = u(新) * 2^k;

3、随机出x,x为[2,n),判断 x ^(u*2^k)%n == 1, 式子分解  [(x^u)%n ]^(2^k) %n == 1; 先计算 x= x ^ u % n;然后计算 x^(2^k) % n == 1;

4、如何计算x^(2^k) = (x^2)^(2^(k-1));  并且可知,当x^2 % n == 1时,无需计算2^(k-1);  当x^2 % n == 1时, x ! = 1 或者 x != n-1则可判断该数为合数

5、循环测试,如果最后都没有return false,则可认为该数时质数。

例题有hdu2138:

  注意点:虽然题目中数字都在32位整型之内,但是再做加法的时候,大小会超。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
using namespace std;
//a容易越界,res容易越界。因为有加号。
int mod_mul(__int64 a,int b,int n)
{
__int64 res = ;
while(b)
{
if(b&) res = (res+a)%n;
a = (*a)%n;
b >>= ;
}
return (int)res;
} int mod_exp(int a,int b,int n)
{
int res = ;
while(b)
{
if(b&) res = mod_mul(res,a,n);
a = mod_mul(a,a,n);
b >>= ;
}
return res;
} bool rabin_miller(int n)
{
if(n== || n== || n== || n== || n== || n==) return true;
if(n<= || n%== || n%== || n%== || n%== || n%== || n%==) return false;
int u,k,x,pre;
u = n-;
k = ;
while(u& ==)
{
++k;
u >>= ;
}
srand(time());
int s = ;
while(s--)
{
x = rand()%(n-)+;
pre = x = mod_exp(x,u,n);
for(int i=;i<k;++i)
{
x = mod_mul(x,x,n);
if(x == && pre != && pre != n-) return false;
pre = x;
}
if(x != ) return false;
}
return true;
} int main()
{
int n;
while(~scanf("%d",&n))
{
int ans = ;
for(int i=;i<n;++i)
{
int a;
scanf("%d",&a);
if(rabin_miller(a))
++ans;
}
printf("%d\n",ans);
} return ;
}

Miller Rabin 大素数测试的更多相关文章

  1. Miller_Rabbin大素数测试

    伪素数: 如果存在和n互素的正整数a满足a^(n-1)≡1(mod n),则n是基于a的伪素数. 是伪素数但不是素数的个数是非常非常少的,所以如果一个数是伪素数,那么他几乎是素数. Miller_Ra ...

  2. Miller-Rabin大素数测试模板

    根据费马小定理: 对于素数n,a(0<a<n),a^(n-1)=1(mod n) 如果对于一个<n的正整数a,a^(n-1)!=1(mod n),则n必不是素数. 然后就可以随机生成 ...

  3. 【算法编程】基于Miller-Rabin的大素数测试

    基本原理: 费尔马小定理:如果p是一个素数,且0<a<p,则a^(p-1)%p=1.        利用费尔马小定理,对于给定的整数n,可以设计素数判定算法,通过计算d=a^(n-1)%n ...

  4. Miller Robin大素数判定

    Miller Robin算法 当要判断的数过大,以至于根n的算法不可行时,可以采用这种方法来判定素数. 用于判断大于2的奇数(2和偶数需要手动判断),是概率意义上的判定,因此需要做多次来减少出错概率. ...

  5. miller——rabin判断素数

    我们首先看这样一个很简单的问题:判定正整数\(n\)是否为素数 最简单的做法就是枚举\(2\)到\(n\)的所有数,看是否有数是\(n\)的因数,时间复杂度\(O(n)\) 稍微优化一下发现只要枚举\ ...

  6. 大素数测试的Miller-Rabin算法

    Miller-Rabin算法本质上是一种概率算法,存在误判的可能性,但是出错的概率非常小.出错的概率到底是多少,存在严格的理论推导. 一.费马小定理 假如p是质数,且gcd(a,p)=1,那么 a(p ...

  7. 大素数测试 求因子 poj 1811

    抄别人的 #include<stdio.h> #include<string.h> #include<algorithm> #include<stdlib.h ...

  8. hdu 6169 Senior PanⅡ Miller_Rabin素数测试+容斥

    Senior PanⅡ Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Pr ...

  9. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

随机推荐

  1. rm -rf & node

    rm -rf & node rm -rf $ rm -rf mydir https://www.computerhope.com/issues/ch000798.htm https://sta ...

  2. [luoguP1474] 货币系统 Money Systems(背包)

    传送门 背包 ——代码 #include <cstdio> #include <iostream> #define LL long long int v, n; LL f[10 ...

  3. Linux command2

    . CentOS 想查看哪个port开了,却提示命令无效 # yum -y install net-tools 2. How to install "wget" command i ...

  4. [bzoj1022/poj3480]小约翰的游戏John_博弈论

    小约翰的游戏John 题目大意:Nim游戏.区别在于取走最后一颗石子这输. 注释:$1\le cases \le 500$,$1\le n\le 50$. 想法:anti-SG游戏Colon定理. 如 ...

  5. Microsoft SQL Server Query Processor Internals and Architecture

    https://msdn.microsoft.com/en-us/library/aa226174(v=sql.70).aspx

  6. MVC之查询demo

    上篇已经说过怎样建立MVC项目.这次主要讲述样例的实现. 其基本的功能就是从数据库中查询一些基本信息. 前边我们已经将实体引入到了项目中,这时Model目录中已经出现了我们建立的newsSystem. ...

  7. 自由宣言--《I Have a Dream》(马丁.路德.金)

    I Have a Dream by Martin Luther King, Jr. I am happy to join with you today in what will go down in ...

  8. J2EE肌肉系统—四层模型

    J2EE是基于JAVA技术的一种标准.为什么会有这种标准呢? 主要是在企业级应用开发其中有一些需求.比如数据库连接,邮件服务.事件处理等,都是一些通用模块. 而这些模块假设由开发者来开发.势必添加开发 ...

  9. 【转】 vsftp上传文件出现553 Could not create file解决方法

    因工作需要,需要搭建一个ftp服务器,我使用ubuntu 10.04操作系统,下载vsftpdy源代码, 进行了编译,安装,然后按照INSTALL文件,创建了用户等操作.    因为时间比较紧,我采用 ...

  10. 全然卸载oracle11g步骤

    iLife's 博客http://blog.csdn.net/fei1502816 全然卸载oracle11g步骤: 1. 開始->设置->控制面板->管理工具->服务 停止全 ...