Loading [MathJax]/extensions/TeX/mathchoice.js

Miller Rabin算法学习笔记

Miller Rabin算法学习笔记

Miller Rabin是一种快速的随机化的素数测定方法。

它基于以下定理

二次探测定理:若x^2\equiv1\pmod p,则x\equiv±1\pmod p

证明大概就是(x-1)(x+1)\equiv0\pmod p

然后我们选取一个底a,设你当前要判断的数为x

初始我们判断a^{x-1}是否为1,不是判定x为合数

然后判断a^{\frac {x-1}2}是否为1p-1,不是判定x为合数

如此反复,直到指数是奇数或余数为p-1为止。

于是此时我们就认为x通过了基于a为底的测试。

一次测试错误率大概是\frac 14

多次测试的错误率一般认为是\frac 1{4^x}的,可以接受。

代码就直接模拟就可以了。

upd:我们可以优化一下,从后往前检测,如果其中有一个通过了二次探测,就判定x是质数。

优化后代码:

/*bool Test(ll a,ll x)
{
	if(a>=x)return 1;
	ll ret=qpow(a,x-1,x),s=x^1;
	while(ret==1&&!(s&1))s>>=1,ret=qpow(a,s,x);
	return ret==1||ret==(x^1);
}*/
bool Test(ll a,ll x)
{
	if(a>=x)return 1;
	ll ret,s=x^1;
	int p=__builtin_ctzll(s);
	ret=qpow(a,s>>p,x);
	if(ret==1||ret==(x^1))return 1;
	while(p--&&ret!=(x^1))ret=mul(ret,ret,x);
	return p>=0;
}
int lst[]={2,3,5,7,11,13,17,19,23};
bool Miller_Rabin(ll x)
{
	if(x==1)return 0;
	if(x==2)return 1;
	if(x&1)
	{
		for(int i=0;i<9;++i)if(!Test(lst[i],x))return 0;
		return 1;
	}
	return 0;
}

2st\ upd:在一般是选2,3,7,61,24251为基底,此时在1e16内只有46856248255981是强伪素数。

posted @   Adscn  阅读(170)  评论(0编辑  收藏  举报
编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· C# 13 中的新增功能实操
· Supergateway:MCP服务器的远程调试与集成工具
点击右上角即可分享
微信分享提示