素数判定Miller_Rabin

Miller–Rabin 素性测试 阅读详情

素数判定Miller_Rabin  算法详解


上次说好的要把素数判定和大数分解(见另一篇博文)的快速随机化算法解决了,于是乎今天就来解决,不得不说理解起来真的有困难。我只能大概的将思路理一下,若有错漏还请担待。

首先相信有一些数学和编程经验的读者应该知道,最简单直观简单的素数判定方法就是试除法。对于判断数n是否是素数,我们从2开始一直到sqrt(n)。如果找到一个因子则判断n不是素数,否则是素数。代码如下:

  1. bool isPrime( long long n )  
  2. {  
  3.     for(long long i = 2; i*i <= n; i++)  
  4.     {  
  5.         if(n%i == 0) return false;  
  6.     }  
  7.     return true;  
  8. }  
bool isPrime( long long n )
{
	for(long long i = 2; i*i <= n; i++)
	{
		if(n%i == 0) return false;
	}
	return true;
}

如果要找到成1~n的所有素数那么这个时间代价就变为O(n^2),很多时候是不可接受的。
所以随着学习的深入,我们了解到了素数筛法,即从2开始,2的倍数肯定不是素数,再向右扫描,如果扫描到素数,则重复之前的过程,剔除之后的部分合数(准确的说是关于当前质数的倍数),如果扫描到合数则跳过(表示前面已经更新过这个数不是素数)。然后都扫描一遍即可把1~n的素数求解出来。这个算法的复杂度略高于O(n)。素数筛代码如下:
  1. #include<iostream>  
  2. #include<cstring>  
  3. using namespace std;  
  4.   
  5. const int MAXN = 500000;  
  6.   
  7. bool isprime[MAXN];  
  8. int prime[MAXN];  
  9. int cnt = 0;//保存素数个数  
  10. void getPrime()  
  11. {  
  12.     for(int i = 1; i < MAXN; i++)  
  13.         isprime[i] = true; //先假设所有数是素数,后面逐个扫描更新  
  14.     for(int i = 2; i < MAXN; i++) //扫一遍  
  15.     {  
  16.         if(!isprime[i]) continue; //如果不是素数,则不往后面更新  
  17.           
  18.         prime[cnt++] = i;  
  19.         for(int j = 2 * i; j < MAXN; j += i)  
  20.             isprime[j] = false;  
  21.     }  
  22. }  
  23.   
  24. int main()  
  25. {  
  26.     getPrime();  
  27.     for(int i = 0; i < cnt; i++)  
  28.         cout << prime[i] << endl;  
  29. }  
#include<iostream>
#include<cstring>
using namespace std;

const int MAXN = 500000;

bool isprime[MAXN];
int prime[MAXN];
int cnt = 0;//保存素数个数
void getPrime()
{
	for(int i = 1; i < MAXN; i++)
		isprime[i] = true; //先假设所有数是素数,后面逐个扫描更新
	for(int i = 2; i < MAXN; i++) //扫一遍
	{
		if(!isprime[i]) continue; //如果不是素数,则不往后面更新
		
		prime[cnt++] = i;
		for(int j = 2 * i; j < MAXN; j += i)
			isprime[j] = false;
	}
}

int main()
{
	getPrime();
	for(int i = 0; i < cnt; i++)
		cout << prime[i] << endl;
}
但是这个算法的弊端在于,为了判断一个大数是否是素数必须从从头开始扫描,而且空间代价也受不了,故不能离散的判断。

---------------------------------------------------------------------------------------------------------------------------------------------

于是进入我们今天的主题,Miller_rabin算法,优势可以单独判断一个大数是否素数。缺点他是一个不保证正确的算法,我们只能通过多次执行算法让这个错误的概率很小,不过幸运的是通常来看它的错误概率可以小到忽略不计。


Miller_rabin算法描述
算法的理论基础:
1. Fermat定理:若n是奇素数,a是任意正整数(1≤ a≤ n−1),则 a^(n-1) ≡ 1 mod n。
2. 推演自Fermat定理(具体过程我没看懂,Orz), 如果n是一个奇素数,将n−1表示成2^s*r的形式,r是奇数,a与n是互素的任何随机整数,那么a^r ≡ 1 mod n或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n 成立。

聪明的读者已经发现上述的定理是一个数是素数的必要条件而非充分条件,所以这就是这个算法的不精确的原有,对于一些特定的检验算子a,存在一些合数也满足上述定理。所以我们要多找几个a反复检验,这样能让错误率大大降低。

那么我们按照上述的定理2,首先重复n次实验。对于每一次实验,随机取检验算子a,带入定理2进行检验,看看在算子a下,n能否满足
a^r ≡ 1 mod n或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n       **
如果任意一次实验不满足,则判定不是素数,如果都满足,可近似可以认为是素数(错误率极小)。

代码实现如下:(代码中的q_mul和q_pow表示快速乘法和快速幂运算,具体讲解请参考另一篇博文)

  1. #include <iostream>   
  2. #include <cstdio>   
  3. #include <algorithm>    
  4. #include <cmath>    
  5. #include <cstring>    
  6. #include <map>    
  7. using namespace std;  
  8.   
  9. const int times = 20;  
  10. int number = 0;  
  11.   
  12. map<long long, int>m;  
  13. long long Random( long long n )         //生成[ 0 , n ]的随机数  
  14. {  
  15.     return ((double)rand( ) / RAND_MAX*n + 0.5);  
  16. }  
  17.   
  18. long long q_mul( long long a, long long b, long long mod ) //快速计算 (a*b) % mod  
  19. {  
  20.     long long ans = 0;  
  21.     while(b)  
  22.     {  
  23.         if(b & 1)  
  24.         {  
  25.             b--;  
  26.             ans =(ans+ a)%mod;  
  27.         }  
  28.         b /= 2;  
  29.         a = (a + a) % mod;  
  30.   
  31.     }  
  32.     return ans;  
  33. }  
  34.   
  35. long long q_pow( long long a, long long b, long long mod ) //快速计算 (a^b) % mod  
  36. {  
  37.     long long ans = 1;  
  38.     while(b)  
  39.     {  
  40.         if(b & 1)  
  41.         {  
  42.             ans = q_mul( ans, a, mod );  
  43.         }  
  44.         b /= 2;  
  45.         a = q_mul( a, a, mod );  
  46.     }  
  47.     return ans;  
  48. }  
  49.   
  50. bool witness( long long a, long long n )//miller_rabin算法的精华  
  51. {//用检验算子a来检验n是不是素数  
  52.     long long tem = n - 1;  
  53.     int j = 0;  
  54.     while(tem % 2 == 0)  
  55.     {  
  56.         tem /= 2;  
  57.         j++;  
  58.     }  
  59.     //将n-1拆分为a^r * s  
  60.   
  61.     long long x = q_pow( a, tem, n ); //得到a^r mod n  
  62.     if(x == 1 || x == n - 1) return true;   //余数为1则为素数  
  63.     while(j--) //否则试验条件2看是否有满足的 j  
  64.     {  
  65.         x = q_mul( x, x, n );  
  66.         if(x == n - 1) return true;  
  67.     }  
  68.     return false;  
  69. }  
  70.   
  71. bool miller_rabin( long long n )  //检验n是否是素数  
  72. {  
  73.   
  74.     if(n == 2)  
  75.         return true;  
  76.     if(n < 2 || n % 2 == 0)  
  77.         return false;               //如果是2则是素数,如果<2或者是>2的偶数则不是素数  
  78.   
  79.     for(int i = 1; i <= times; i++)  //做times次随机检验  
  80.     {  
  81.         long long a = Random( n - 2 ) + 1; //得到随机检验算子 a  
  82.         if(!witness( a, n ))                        //用a检验n是否是素数  
  83.             return false;  
  84.     }  
  85.     return true;  
  86. }  
  87.   
  88.   
  89. int main( )  
  90. {  
  91.     long long tar;  
  92.     while(cin >> tar)  
  93.     {  
  94.         if(miller_rabin( tar )) //检验tar是不是素数  
  95.             cout << "Yes, Prime!" << endl;  
  96.         else  
  97.             cout << "No, not prime.." << endl;  
  98.     }  
  99.     return 0;  
  100. }  
#include <iostream> 
#include <cstdio> 
#include <algorithm>  
#include <cmath>  
#include <cstring>  
#include <map>  
using namespace std;

const int times = 20;
int number = 0;

map<long long, int>m;
long long Random( long long n )			//生成[ 0 , n ]的随机数
{
	return ((double)rand( ) / RAND_MAX*n + 0.5);
}

long long q_mul( long long a, long long b, long long mod ) //快速计算 (a*b) % mod
{
	long long ans = 0;
	while(b)
	{
		if(b & 1)
		{
			b--;
			ans =(ans+ a)%mod;
		}
		b /= 2;
		a = (a + a) % mod;

	}
	return ans;
}

long long q_pow( long long a, long long b, long long mod ) //快速计算 (a^b) % mod
{
	long long ans = 1;
	while(b)
	{
		if(b & 1)
		{
			ans = q_mul( ans, a, mod );
		}
		b /= 2;
		a = q_mul( a, a, mod );
	}
	return ans;
}

bool witness( long long a, long long n )//miller_rabin算法的精华
{//用检验算子a来检验n是不是素数
	long long tem = n - 1;
	int j = 0;
	while(tem % 2 == 0)
	{
		tem /= 2;
		j++;
	}
	//将n-1拆分为a^r * s

	long long x = q_pow( a, tem, n ); //得到a^r mod n
	if(x == 1 || x == n - 1) return true;	//余数为1则为素数
	while(j--) //否则试验条件2看是否有满足的 j
	{
		x = q_mul( x, x, n );
		if(x == n - 1) return true;
	}
	return false;
}

bool miller_rabin( long long n )  //检验n是否是素数
{

	if(n == 2)
		return true;
	if(n < 2 || n % 2 == 0)
		return false;				//如果是2则是素数,如果<2或者是>2的偶数则不是素数

	for(int i = 1; i <= times; i++)  //做times次随机检验
	{
		long long a = Random( n - 2 ) + 1; //得到随机检验算子 a
		if(!witness( a, n ))						//用a检验n是否是素数
			return false;
	}
	return true;
}


int main( )
{
	long long tar;
	while(cin >> tar)
	{
		if(miller_rabin( tar ))	//检验tar是不是素数
			cout << "Yes, Prime!" << endl;
		else
			cout << "No, not prime.." << endl;
	}
	return 0;
}

嗯,就是这样,至于那个定理我真的不是很清楚为何为这样,有一篇讲解文你们有兴趣的话看看吧。
Miller–Rabin 素性检验算法 算法介绍 Miller-Rabin素数检验或Rabin-Miller素数检验是一种概率素数检验:一种确定给定数是否可能是素数的算法,类似于费马素数检验和Solovay-Strassen素数检验。作为实践中使用比较广泛的素性检验算法的一种, Miller-Rabin算法最早在1976年由Gary L. Miller提出(当时该算法是确定性的), 并在1980年由Michael O. Rabin改进为无条件的概率算法. 数学原理 算法的主要思想就是检验数是否满足特定的素数条件, 这些条件在Miller-Rabi 阅读详情

相关推荐

Miller-Rabin素数检验算法原理与密码学应用

素数检验是密码学中的基础算法,用于验证大整数的素性。Miller-Rabin算法作为概率性检验方法,通过扩展费马小定理实现高效判断,其核心原理是将n-1分解为2^s*d形式并进行模幂运算验证。该算法在RSA密钥生成等场景中具有重要价值,通过调整测试轮数k可平衡效率与准确性,典型应用中采用k=40-64轮可将错误概率降至2^-128以下。现代密码学系统普遍依赖此类高效素性测试来保障密钥安全,特别是处理2048位大素数时,优化后的Miller-Rabin算法能在数秒内完成可靠判断。

weixin_29741447的博客 259

素性检测(Miller-Rabin)

一.素性检测(MIller-Rabin) 1.一些基础知识点 (1)位运算 n&1 这里 n&1 就是——判断n是否为奇数 因为n为奇数时,对应的二进制数最低位一定为1,n&1的结果就是1 n为偶数时,相应的最低位为0,n&1的结果就是0. 1&n 这里的 1&n 就是: 检查二进制n的最低位,若为1,则1&n的结果就是1, 若不为1,则1&n的结果就是0. 按位与运算符(&) 参加运算的两个数据,按二进制位进行“与”运算。 运算规则

qq_45031509的博客 6909

素数判定之Miller-Rabin算法

费马小定理 P为素数时, 二次探测原理 所以 结合起来 对于p-1,将其分解,因为p为素数,所以一定是奇数(2被特判掉了),那么p-1为偶数, 因此可以通过将p-1不断除2(直到除成奇数),将p-1分解为u*(2^k)的形式,其中u为奇数 那么,随机一个数a,计算a^u,然后不断将其平方(二次探测原理),判断是不是素数, 最后计算到a^(p-1),的时候看其是否为1(费...

这里RevolIA,_(:з」∠)_ 1163

Miller-Rabin算法

算法背景 米勒-拉宾素性检验(Miller Rabin算法),是一种素数判定法则,利用随机化算法判断一个数是合数还是可能是素数。卡内基梅隆大学的计算机系教授Gary Lee Miller首先提出了基于广义黎曼猜想的确定性算法,由于广义黎曼猜想并没有被证明,其后由以色列耶路撒冷希伯来大学的Michael O. Rabin教授作出修改,提出了不依赖于该假设的随机化算法。 涉及知识点 费马小定理 费马小...

qq_43227036的博客 9675

素数判定的一些讨论(Miller-Rabin算法)

很久没有写博客了。。。最近军训加开学,感觉刷题速度有降低,要补一补。 回归正题,正式进入数论阶段,讨论一下关于素数判定的那些事。 一类问题: 判定一个整数n(n>1)是否为素数。 算法1: 直接根据素数的定义枚举ii从22到(n−1)(n-1),如果n%i==0nn为合数。 时间复杂度:O(n)O(n) bool is_prime(int n) { int i;

Sunshine_cfbsl 4350

素数判定——Miller Rabin 算法

最近复习备战NOIP,开始回顾NOIP基础知识(才发现这么多不会= =b)首先过关的是基础数论知识,从素数判定开始学起。谈到素数判定,首先想到的两种便是暴力判定与筛法,实现非常简单,在此不提。但在分解大质数时,由于数字过大,使得暴力判定会超时,筛法会超空间(可使用有技巧的限制空间筛法,但数字过大仍然过不了)这时,我们就要引入非完美大质数判定算法——Miller Rabin算法。下面一段引自sunsh

xffyjq的博客 817

素数判定Miller_Rabin 算法详解

素数判定Miller_Rabin  算法详解 上次说好的要把素数判定和大数分解(见另一篇博文)的快速随机化算法解决了,于是乎今天就来解决,不得不说理解起来真的有困难。我只能大概的将思路理一下,若有错漏还请担待。

JUST CODE 2万+

【知识点】大数分解与素数判定 --- 【Miller-rabin算法】【pollard-rho算法】

1.Miller-rabin算法: Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法。 根据费马小定理,如果p是素数,则a^(p-1)≡1(mod p)对所有的a∈[1,n-1]成立。所以如果在[1,n-1]中随机取出一个a,发现不满足费马小定理,则证明n必为合数。 为了计算a^(n-1)mod n,我们把n-1分解为u* 2^t的形式,其中t>=1且u是奇数;因

咸鱼の小窝 1858

Miller_Rabin素数判定

参考的一篇很棒的文章         参考的另一篇很棒的文章 Miller_Rabin素数判定 对于素数判定,首先知道最朴素的方法——试除法。从2到sqrt(N),复杂度O (sqrt(N))当然,如果把素数预处理出来,复杂度要优秀一些。由素数分布定理:对正实数x,定义π(x)为素数计数函数,即不大于x的素数个数,则有: 处理出素数以后,只试除2到sqrt(N)之间的素数,复杂度约为。然而对...

g21wcr的博客 704

【Python Turtle合集】有趣好玩的代码当然要分享给大家啦~(皮卡丘、玫瑰花、小黄人......)

前言 🚀 作者 :“程序员梨子” 🚀 **文章简介 **:本篇文章主要是写了利用Turtle库绘制四种不一样的图案的小程序! 🚀 **文章源码免费获取 : 为了感谢每一个关注我的小可爱💓每篇文章的项目源码都是无 偿分享滴💓👇👇👇👇 点这里蓝色这行字体自取,需要什么源码记得说标题名字哈!私信我也可! 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 正文 今天给大家介绍一个好玩儿的库,嘻嘻! Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵

TZ45678的博客 3万+

离散数学期末考试试卷(两套)-熟悉题型

3.设集合A={a,b,c,d}上有自反关系R={,,,,},对称关系S={,,,}。6.设集合A={1,2,3},B={u,v,w},C={a,b,c},f是集合A到集合B上的映射,g是集合B到集合C上的映射,f={, , },g={},则复合函数g。5. 设集合A={a,b,c,d,e},下列选项中哪一个集合不是A的划分( )。

muse3159546973的博客 6952

素数判定 Miller-Rabin 算法的实现 python

素数判定 Miller-Rabin 算法的实现 实验目的 通过实验掌握 Miller-Rabin 素数判定的算法。 实验原理 Miller-Rabin primality test | encyclopedia article by TheFreeDictionary Miller-Rabin 素性测试或 Rabin-Miller 素性测试是一种概率素性测试: 一种判断给定数字是否可能为素数的算法,类似于费马素性检验和 Solovay-Strassen 素性测试。 强概要素数:对于一个给定的奇数整数 n &

SKPrimin的博客 1821

CS5212芯片实战:手把手教你设计DP转VGA转换电路(附完整原理图)

本文详细介绍了CS5212芯片在DP转VGA转换电路设计中的实战应用,包括芯片架构解析、核心电路设计要点、PCB布局与电磁兼容设计、调试技巧及进阶应用开发。通过完整的原理图和实用设计指南,帮助工程师快速掌握高可靠转换器的设计方法,特别适合需要国产化替代方案的场景。

weixin_30576827的博客 390

Miller-Rabin素数判定

素数判定

mqnu0的博客 427

校园网改造实录:手把手教你用华为MA5800 OLT调试全光网(附常用排错命令)

本文详细记录了校园全光网改造中华为MA5800 OLT的部署与调试过程,涵盖设备选型、基础配置、ONU批量部署及高频故障排查。通过实战案例和排错命令,帮助网络工程师快速掌握全光网调试技巧,实现低延迟、高稳定的网络性能。

weixin_42552716的博客 572

西门子 标准程序解读---> 机器手抓取和涂胶控制程序

摘要 该程序实现机械手在OP70/OP90工位的自动化控制,核心功能包括: 流程控制:分段(Seg1-Seg11)管理抓件、涂胶、放件等动作,结合DB1050/DB1250数据块监控工位状态及变位机位置反馈。 安全机制:配置干涉区(FC124)、实时检测安全光/急停信号,防止碰撞;服务程序(FB191)支持维修位触发与安全隔离。 参数配置:通过DB块关联机器人速度、节拍(FB27)、车型编码(如空过=2)及手自动模式(DB70.DBX21.2)。 应用场景:适用于汽车焊接/装配线

工控智联驿站 1238

实现Miller-Rabin素数判定算法

Miller-Rabin素数判定法是典型的大数素性测试算法。 利用欧拉筛生成1e7个素数(即从2开始的前10000000个素数) int prime[MAXN]; bool vis[MAXN]; int cnt = 0; void Euler_prime(int n) { for (int i = 2; i <= n; ++i) { if (!vis[i]) { prime[cnt++] = i; vis[i] = true

HUANGliang_的博客 1317

华为OD机试真题 新系统【优化充电桩调度算法】

华为OD机试 新系统真题【优化充电桩调度算法】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【优化充电桩调度算法】

qq_45776114的博客 752

素数判定Miller-Rabin算法的实现

编程实现Miller-Rabin素数判定算法,并判断23456789是否是素数

weixin_58628068的博客 655

量化交易python代码解析:从狙击手算法到最优限价算法

在金融市场的竞技场上,量化交易如同一位冷静的策略大师,它以数学模型为剑,以计算机程序为盾,精准出击,捕捉市场的微妙波动。本文将深入探讨五种核心量化交易算法:直接委托算法(DMA)、时间加权平均算法(TWAP)、冰山算法(Iceberg)、狙击手算法(Sniper)、条件委托算法(Stop)以及最优限价算法(BestLimit),揭开它们背后的运作机制与实战应用。

木头大左的博客 1884

Java与OSG的梦幻联动:深入编译OpenSceneGraph的Java JNI桥梁,开启3D视觉盛宴的奇幻之旅

🔥关注墨瑾轩,带你探索编程的奥秘!🚀🔥超萌技术攻略,轻松晋级编程高手🚀🔥技术宝库已备好,就等你来挖掘🚀🔥订阅墨瑾轩,智趣学习不孤单🚀🔥即刻启航,编程之旅更有趣🚀在编译OpenSceneGraph (OSG) 的Java版本时,首先需要了解OSG本身是一个主要用于3D图形和视觉仿真的开源库,它主要支持C++。然而,OSG 也支持通过JNI(Java Native Interface)与Java集成,这允许Java程序调用OSG的C++库。

java专栏 868

10^9以上素数判定,Miller_Rabin算法

#include<iostream> #include<cstdio> #include<ctime> #include<string.h> #include<stdlib.h> #define LL long long using namespace std; const int S=20;//随机算法判...

awang50683的博客 520

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

如何高效判定素数:Miller-Rabin与埃氏筛法终极指南

在算法学习和编程竞赛中,素数判定是一个基础而重要的主题。无论是简单的试除法还是高效的Miller-Rabin算法和埃拉托斯特尼筛法,掌握这些方法对于解决LeetCode等平台上的数学问题至关重要。本文将为你详细介绍两种主流的素数判定算法,帮助你在算法之路上更进一步。 ## 什么是素数?为什么需要高效判定? 素数(质数)是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。素数在密码学、计

gitblog_01130的博客 783

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 类模板中的友元声明
Tsinting
博客等级 码龄10年 3粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值