miller素数判断

文章详细解释了一个用于检测质数的算法,该算法基于二次探测定理和生成元定理。首先将待检测数表示为奇数和2的幂的乘积,然后通过平方并模运算检查是否为1或素数的阶乘,以此判断是否为合数。若在模运算中未回到1,则说明不是素数。文章附带了C++代码示例来演示这一过程。
摘要由CSDN通过智能技术生成

写在前面的话: 我已经无数次用过这个函数了,但是每一次都不是很理解,总是忘了里面的原理,还是写下来记录一下吧.

算法过程描述:
4 4 4个质数 t e s t test test { 2 , 3 , 5 , 7 } \left \{ 2,3,5,7 \right \} {2,3,5,7},设检测的数为 p p p,并且设 x x x p − 1 p-1 p1。先将 x x x表示成 q ∗ 2 k q*2^{k} q2k(其中 k k k为非负整数, q q q为奇数),然后 ∀ i \forall i i,设定初始值 a a a ( t e s t [ i ] ) q (test[i])^{q} (test[i])q。每次计算 a a a的平方(在模 p p p运算下) t m p tmp tmp,如果 t m p tmp tmp 1 1 1,那么 a a a应该为 1 1 1或者 p − 1 p-1 p1,否则 x x x为合数。将 t m p tmp tmp赋值给 a a a ∀ i \forall i i,上述过程重复 k k k次,最后 a a a如果不是 1 1 1, x x x为合数。

涉及定理:

  1. 二次探测定理
    对上述过程的疑问1:
         \space\space\space\space     引自过程描述: 如果 t m p tmp tmp 1 1 1,那么 a a a应该为 1 1 1或者 p − 1 p-1 p1,否则 x x x为合数。
         \space\space\space\space     证明: 由上述过程容易得: a 2 ≡ 1   m o d   p a^2\equiv 1 \space mod\space p a21 mod p,则应该有 ( a 2 − 1 ) ≡ 0   m o d   p (a^{2}-1)\equiv 0 \space mod\space p (a21)0 mod p。所以容易得到: p ∣ ( a − 1 ) ( a + 1 ) p|(a-1)(a+1) p(a1)(a+1)。.进一步来看, a − 1 a-1 a1 a + 1 a+1 a+1应该为 p p p的倍数(在模 p p p条件下, a a a 1 1 1或者 p − 1 p-1 p1),否则的话,( a − 1 a-1 a1)和( a + 1 a+1 a+1)一定有两个因子或更多满足 b 1 ∗ b 2 ∗ b 3 ∗ . . . . = p b_{1}*b_{2}*b{3}*....=p b1b2b3....=p,则此时 p p p不是素数。

  2. 生成元定理
    对上述过程的疑问2:
         \space\space\space\space     引自过程描述: 最后 a a a如果不是 1 1 1, x x x为合数
         \space\space\space\space     证明:由过程描述容易看出 t e s t [ i ] test[i] test[i]为素数,所以在 m o d   p mod\space p mod p的域中, t e s t [ i ] test[i] test[i]为生成元,所以经过 p − 1 p-1 p1次转动之后即 ( t e s t [ i ] ) p − 1 (test[i])^{p-1} (test[i])p1一定能转回到 1 1 1.如果没转回来,说明 m o d   p mod\space p mod p不是域,也即 p p p不是素数。这里扩展一下,在 m o d   p mod\space p mod p中, x x x的逆元为 x p − 2 x^{p-2} xp2,如果 p p p较大,可以采用快速幂。

嗯,感觉现在懂了一点,放个代码吧,若您对我的描述有任何问题欢迎指出!

#include<bits/stdc++.h>
typedef long long ll;
int pow(int a, int b, int p)
{
	int tmp = b;
	int k = 0;
	int sum = 1;
	while (b)
	{
		if (b % 2 == 1)
		{
			sum = ((ll)sum*a) % p;
		}
		a = ((ll)a*a) % p;
		b = b >> 1;
	}
	return sum;
}
int test[4] = { 2,3,5,7 };//这个test[i]做的是a,然后指数上是t
int rho(int x)
{
	int p = x;
	int k = 0;
	//for (int i = 0; i < 4; i++)
		//if (x == test[i])return 1;
	x--;
	while (!(x & 1))
	{
		x = x >> 1; k++;
	}
	for (int i = 0; i < 4; i++)
	{
		//if (test[i] == p)return 1;
		if (test[i] == p)return 1;
		int a = pow(test[i], x, p);//这步很关键,做平方的时候是a的t次幂,不是a
		//同时有p=a^(t*2^k),这里,x=t,x已经被÷2处理过了
		int nxt=a;
		for (int j = 0; j < k; j++)
		{
			nxt = ((ll)a*a) % p;
			if (nxt == 1 && a != 1 && a != p-1)
				return 0;
			a = nxt;
		}
		if (nxt != 1)
			return 0;
	}
	return 1;
}
int main(void)
{
	int n;
	scanf_s("%d", &n);
	int count = 0;
	for (int i = 2; i <= n; i++)
	{
		//for(int j=0;j<test[i])
		if (rho(i))count++;
	}
	printf("%d", count);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值