miller_rabin
log(n)级别复杂度的判断素数的方式
一个引理:(1^2~mod~p) 和 ((-1)^2~mod~p)总是得到1,称这两个数为1的“平凡平方根”。当(p)是素数且(p>2)时,不存在(1~mod~p)的“非平凡平方根”。我们假设(x)是(1~mod~p)的平方根有$$x^2≡1(mod~p)$$
[(x+1)(x-1)≡1(mod~p)
]
[p|(x+1),p|(x-1)
]
算法
假设(n)是一个质数,那么(n-1)是一个偶数,我们把(n-1)表示成(d×2^s)的形式,(s)和(d)都是正整数且(d)是奇数,对任意在正整数内的(a)和(0≤r≤s-1),必满足下列一个式子
[a^d ≡ 1(mod~n)
]
[a^{2^rd}≡n-1(mod~n)
]
于是代码
#include <cstdio>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
int prime[8] = {2,3,5,7,13,29,37,89};//用来测试
LL quickpower(LL a,LL b,LL p)
{
LL res = 1;
while(b)
{
if(b & 1)
res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res % p;
}
bool miller_rabin(int a,int n)
{
int d = n - 1,r = 0;
while(!(d & 1))
{
d >>= 1;
r ++;
}
LL x = quickpower(a,d,n);
if(x == 1) return true;
for(int i=0;i<r;i++)
{
if(x == n-1) return true;
x = x * x % n;
}
return false;
}
//总之,若 n 是素数,则 a^d = 1(mod n)
//或 存在0 ≤i < r使(a ^ (d * 2^i)) = n-1(mod n)
bool is_prime(int n)
{
if(n <= 1) return false;
for(int i=0;i<=7;i++)
if(n == prime[i]) return true;
for(int i=0;i<=7;i++)
if(!miller_rabin(prime[i],n)) return false;
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
if(is_prime(n))
{
printf("%d是素数
",n);
continue;
}
else printf("%d不是素数
",n);
}
return 0;
}