额,我们今天来讲一讲Miller-Rabin素性测试算法。

读者:怎么又是随机算法!!!(⊙o⊙)…

【好了,言归正传】

【费马小定理】

费马小定理只是个必要条件,符合费马小定理而非素数的数叫做Carmichael

Carmichael数是非常少的。

在1~100000000范围内的整数中,只有255个Carmichael数。

为此又有二次探测定理,以确保该数为素数。

这就构成了Miller-Rabin的基本原理 ╰( ̄▽ ̄)╭

【二次探测定理】

二次探测定理 如果p是一个素数,0<x<p,则方程x^2≡1(mod p)的解为x=1,p-1

【Miller-Rabin】

让我们来模拟一下:

第一步:先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数

第二步:随机取一个b,2<=b

第三步:计算v=b^m mod n

第四步:如果v==1,通过测试,返回

第五步:令i=1

第六步:如果v=n-1,通过测试,返回

第七步:如果i==j,非素数,结束

第八步:v=v^2 mod n,i=i+1

第九步:循环到S(S根据数据进行改变)

【算法分析】

既然是随机算法,那么我们就来计算一下这种算法的正确率。

Miller-Rabin的正确率为75%。

怎么这么低(⊙o⊙)…,你可以多调用几次就好了!这样可以使正确概率提高为1-(1/4)^S

【代码】

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

P.S. 感谢吉林大学的模板,当然这已经改过了,进行了优化。

【你以为这就完了?】

下面我们来研究一下Miller-Rabin的更高效算法

【代码】

#include<windows.h>
#include<iostream>
#include<time.h>
#include<cstdio>
#include<cmath>
using namespace std;
bool witness(long long a,long long n)
{
long long t,d,x;
d=1;
int i=ceil(log(n-1.0)/log(2.0)) - 1;
for(;i>=0;i--)
{
x=d; d=(d*d)%n;
if(d==1 && x!=1 && x!=n-1) return true;
if( ((n-1) & (1<<i)) > 0)
d=(d*a)%n;
}
return d==1? false : true;
}
bool miller_rabin(long long n)
{
int s[]={2,7,61};
if(n==2) return true;
if(n==1 || ((n&1)==0)) return false;
for(int i=0;i<3;i++)//注意这里的i<3不可以改,因为每次S都只为2,7,61!
if(witness(s[i], n)) return false;
return true;
}
int main()
{
long long n;
scanf("%lld",&n);
cout<<miller_rabin(n);
//system("pause");
return 0;
}

我们发现,它只调用witness函数3次,每次都a为2,7,61。时间很快啊。

但正确率……

:-D   //迷之微笑

【算法杂谈】Miller-Rabin素性测试算法的更多相关文章

  1. 关于Miller-Rabin与Pollard-Rho算法的理解(素性测试与质因数分解)

    前置 费马小定理(即若P为质数,则\(A^P\equiv A \pmod{P}\)). 欧几里得算法(GCD). 快速幂,龟速乘. 素性测试 引入 素性测试是OI中一个十分重要的事,在数学毒瘤题中有着 ...

  2. POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  3. HDU1164_Eddy&#39;s research I【Miller Rabin素数测试】【Pollar Rho整数分解】

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. 优化后的二次测试Miller_Rabin素性测试算法

    ll random(ll n) { return (ll)((double)rand()/RAND_MAX*n + 0.5); } ll pow_mod(ll a,ll p,ll n) { ) ; l ...

  5. Miller Rabin算法学习笔记

    定义: Miller Rabin算法是一个随机化素数测试算法,作用是判断一个数是否是素数,且只要你脸不黑以及常数不要巨大一般来讲都比\(O(\sqrt n)\)的朴素做法更快. 定理: Miller ...

  6. 【数论基础】素数判定和Miller Rabin算法

    判断正整数p是否是素数 方法一 朴素的判定   

  7. (Miller Rabin算法)判断一个数是否为素数

    1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先级高于乘除和取模,加减的优先级最低. 见到x^y/z这 ...

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

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

  9. 素数与素性测试(Miller-Rabin测试)

    转载自Matrix大牛的博客 把代码翻译成C++ http://www.matrix67.com/blog/archives/234 题目链接: http://hihocoder.com/proble ...

随机推荐

  1. hashMap 深入理解

    1.java 的hashMap 是通过 链地址 法来解决 hash冲突的 2.初始时是一个empty table, 第一次添加数据时检查到时空数组就会 生成指定容量的数组,也就是 在第一次使用时才初始 ...

  2. URI编码解码

    .NET string s= System.Web.HttpUtility.UrlEncode("123", System.Text.Encoding.Unicode); //编码 ...

  3. JS学习:第二周——NO.4DOM库

    DOM库封装练习 var utils = (function () { var flg = 'getComputedStyle' in window;//惰性思想的运用: function makeA ...

  4. Archlinux安装MySQL5.7.14压缩包版

    现在Arch官方源里是MariaDB,MySQL扔到AUR里去了...感觉还是自己安装好些... (参考资料:度娘.官方文档) 贴配置: lts版的 在Vbox虚拟机测试 按照官方文档的安装步骤: 创 ...

  5. bodyParser中间件的研究

    原文链接: bodyParser中间件 bodyParser中间件用来解析http请求体,是express默认使用的中间件之一. 使用express应用生成器生成一个网站,它默认已经使用了 bodyP ...

  6. 【java回调】java两个类之间的回调函数传递

    背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...

  7. 51. 顺时针打印矩阵[print matrix in clockwise direction]

    [本文链接] http://www.cnblogs.com/hellogiser/p/print-matrix-in-clockwise-direction.html [题目] 输入一个矩阵,按照从外 ...

  8. windows 中去除Ctrl+Alt+Del才能登录

    安装windows 7后登录的时候有一样很麻烦的步骤是需要先按Ctrl+Alt+Del,才能输入用户密码进行登录.这里笔者介绍一下如何取消这个东西. 点击“开始菜单”,点击“控制面板”. [管理工具] ...

  9. IDEA tomcat乱码

    在运行/调试 配置对话框的Startup/Connection面板中, 勾选Pass environment variables. 并添加一个environment variable, Name填 J ...

  10. MVC Code First 当实体类发生变化时,如何自动更新数据库表

    下面做一个例子,Category是用户新建的一个实体类,然后添加一个字段,然后让数据库中的Category表也添加一个字段 1.Category.cs