算法理论基础
Miller-Rabin算法是Fermat算法的一个变形改进,它的理论基础是由Fermat定理引申而来。
Fermat 定理: n是一个奇素数,a是任何整数(1≤ a≤n-1) ,则 a^(n-1)≡1(mod n)。
Miller-Rabin 算法的理论基础:如果n是一个奇素数, 将n-1表示成2^s*r的形式(r是奇 数),a 是和n互素的任何整数, 那么a^r≡1(mod n) 或者对某个j(0≤j ≤s -1, j∈Z) 等式 a^(2^j*r) ≡-1(mod n)成立。 这个理论是通过一个事实经由Fermat定理推导而来: n是一个奇素数,则方程x^2 ≡ 1 mod n只有±1两个解。
重复n次实验。对于每一次实验,随机取检验算子a,带入定理进行检验,看看在算子a下,n能否满足
a^r ≡ 1 mod n或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n **
如果任意一次实验不满足,则判定不是素数,如果都满足,可近似可以认为是素数(错误率极小)。
取模运算性质
术语:
For a positive integer n, two integers a and b are said to be congruent modulo n, and written as
一些有用的性质(可证明):
如果a≡b(mod m),x≡y(mod m),则a+x≡b+y(mod m)。
如果a≡b(mod m),x≡y(mod m),则ax≡by(mod m)。
如果ac≡bc(mod m),且c和m互质,则a≡b(mod m) (就是说同余式两边可以同时除以一个和模数互质的数)。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
typedef unsigned long long ll;//10^20 左右再大我也很无奈=.=
const int times = 10;//一般10就够了
int prime[] = {2, 3, 5, 7, 13, 17, 11, 61, 97, 24251, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 67, 71, 73, 79, 83, 89}; //得到随机检验算子 a
ll Random(ll n){
return (double(rand())/RAND_MAX * n+0.5);
}
ll q_mul(ll a, ll b, ll mod){
ll ans=0;
while(b){
if(b & 1) ans=(ans+a)%mod;
a=(a<<1)%mod;
b>>=1;
}
return ans;
// return (a*b)%mod;//超时就换成这个
}
ll q_pow(ll a, ll b, ll mod){
ll ans=1;
while(b){
if(b & 1) ans=q_mul(ans,a,mod);
a=q_mul(a,a,mod);
b>>=1;
}
return ans;
}
bool miller_rabin(ll n){ //检验n是否是素数
if(n<2) return false;
if(n==2) return true;
if(!(n&1)) return false; //如果是2则是素数,如果<2或者是>2的偶数则不是素数
ll k,j=0, x, tem = n-1;
while(!(tem & 1)) tem>>=1,j++;
for(int i=0;i<times;i++){ //做times次随机检验
if(prime[i] >= n) return true;
x = q_pow(prime[i], tem, n); //得到a^r mod n
if( x == 1 ) continue; //余数为1则为素数
for(k=0;k<j;k++){
if(x == n-1) break; //否则试验条件2看是否有满足的 j
x = q_mul(x, x, n);
}
if(k == j) return false;
}
return true;
}
int main( )
{
long long tar;
while(scanf("%lld",&tar)){
if(miller_rabin( tar )) //检验tar是不是素数
cout << "Yes, Prime!" << endl;
else
cout << "No, not prime.." << endl;
}
return 0;
}
再大就要手动实现大整数了。。。太麻烦了,可以用java里的BigInteger,里面提供了一个实现这个算法的方法,方法原型是:
boolean isProbablePrime(int certainty)
参考:https://blog.youkuaiyun.com/maxichu/article/details/45458569点击打开链接
https://blog.youkuaiyun.com/chensilly8888/article/details/42834697