miller_rabin大素数随机检测模板

用到两个定理:

  1. 费马小定理

  2. 二次探测定理

如果 p p p 是一个素数, 0 < x < p 0<x<p 0<x<p,则方程 x 2 ≡ 1 ( m o d p ) x^2≡1(mod p) x21(modp) 的解为 x = 1 x=1 x=1 x = p − 1 x=p-1 x=p1

对于待检测数 p p p [ 2 , p ] [2,p] [2,p] 中随机选取 s s s a a a 判断 a ( p − 1 ) ≡ 1 ( m o d p ) a(p-1) ≡ 1(mod p) a(p1)1modp 是否成立 一旦发现不成立则可判定 p p p 不是素数 为了提高正确的概率在求 a ( p − 1 ) a(p-1)%p a(p1) 的过程中用到定理二 令 p − 1 = 2 t ∗ k p-1 = 2^t * k p1=2tk (其中k是奇数) 然后 a ( p − 1 ) a(p-1) a(p1) 就相当于 a k ∗ 2 t ak*2^t ak2t 也就是将 a k ak ak 平方t次 用 x [ i ] x[i] x[i] 来表示平方i次的结果 如果发现 x [ i ] = 1 x[i] = 1 x[i]=1 x [ i − 1 ] x[i-1] x[i1] 既不等于 1 1 1 也不等于 p − 1 p-1 p1 那么就可以判定 p p p 不是素数了 求 a ( p − 1 ) a(p-1)%p a(p1) 的过程用的是快速幂 在用快速幂的过程中还用到了一个大数相乘取模的优化 即化乘法为加法 即模拟两个数相乘的二进制运算过程 每次相加取模 如果 p p p 成功通过检测则判定为素数否则为合数。

Code:
ll x[1005];
ll multi(ll a, ll b, ll p)
{ //      化乘法为加法
	ll temp = 0;
	while (b)
	{
		if (b & (ll)1)
			temp = (temp + a) % p;
		a = (a << 1) % p;
		b >>= 1;
	}
	return temp;
}
ll qpow(ll a, ll b, ll p)
{ //      快速幂
	ll temp = 1;
	while (b)
	{
		if (b & (ll)1)
			temp = multi(temp, a, p);
		b >>= 1;
		a = multi(a, a, p);
	}
	return temp;
}
int miller_rabin(ll n)
{
	if (n == 0 || n == 1)
		return 0;
	if (n == 2)
		return 1;
	int s = 10;
	ll k = n - 1;
	int t = 0;
	while (!(k & (ll)1))
	{
		t++;
		k >>= 1;
	}; //    k如果不是奇数将k转化为奇数
	while (s--)
	{
		ll a = rand() % (n - 2) + 2; //        随机取值
		x[0] = qpow(a, k, n);
		for (int i = 1; i <= t; i++)
		{
			x[i] = multi(x[i - 1], x[i - 1], n); //     记录平方i次的结果
			if (x[i] == 1 && x[i - 1] != 1 && x[i - 1] != n - 1)
				return 0;
		}
		if (x[t] != 1)
			return 0;
	}
	return 1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值