Miller_Rabin算法详解

目录

基本引理:

1,费马定理:

2,二次探测定理:

作用:

证明:

代码实现:


目录

基本引理:

1,费马定理:

2,二次探测定理:


基本引理:

1,费马定理:a^{p-1}=1(mod\ p)

费马定理的证明链接

2,二次探测定理:x^{2}\equiv 1(mod\ p)\Rightarrow x=1||p-1

二次探测定理的证明链接

作用:

有效的检测大整数是否为素数。

证明:

由费马定理,可以排除大部分非素数的情况(满足费马定理是素数的必要条件),给出一个奇素数n,显然n-1为一个偶数,存在a\in (1,n),显然n-1=2^{q}*m(q,m为任意整数)是成立的,所以a^{n-1}=a^{2^{q}*m},显然(a^{n-1}\equiv 1(mod\ n))\Leftrightarrow (a^{2^{q}*m}\equiv 1(mod\ n)).

所以根据二次探测定理,可以推断a^{2^{p-1}*m}\equiv 1||(n-1),a^{2^{q-2}*m}\equiv 1||(n-1)(mod\ n)……,a^{m}\equiv 1||(n-1)(mod\ n).

所以我们只需要证明大整数在每次分解都满足上式就可以大概率的确定n是素数。每次判断的错误率给、大概为0.25,k次运算后的错误率大概是0.25^k,大概8次以上这个错误概率就低到忽略不计了

代码实现:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int times = 10;
ll fast_mod(ll a,ll b,ll mod)//计算2^q的过程
{
    ll res = 0;
    while(b){
        if(b & 1) res = res + a;
        a <<= 1;
        if(a >= mod) a -= mod;
        if(res >= mod) res -= mod;
        b >>= 1;
    }
    return res;
}
ll fast_pow_mod(ll a,ll b,ll mod)//快速幂算出a^m
{
    ll res = 1;
    while(b){
        if(b & 1) res = (res * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return res;
}
bool check(ll a,ll m,ll p,ll n)//对于每次随机的a进行测试
{
    ll temp = fast_pow_mod(a,m,n),ret = temp;
    for(int i = 0;i < p;++i){
        ret = fast_mod(temp,temp,n);
        if(ret == 1 && temp != n - 1 && temp != 1) return true;
        temp = ret;
    }
    return ret != 1;
}
bool Miller_Pabin(ll n)//Miller测试的主体结构
{
    if(n < 2) return false;
    if(n == 2) return true;
    if(n & 1 == 0) return false;//对于偶数的优化
    ll p = 0,x = n - 1;//p为Miller测试的q,x为Miller测试的m
    while(x & 1 == 0){
        x >>= 1;
        p++;
    }
    srand(time(NULL));
    for(int i = 0;i < times;++i){
        ll o = rand() % (n - 1) + 1;//o就是Miller测试的底数a
        if(check(o,x,p,n)) return false;
    }
    return true;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--){
        long long n;
        cin >> n;
        cout << (Miller_Pabin(n) ? "Prime" : "Not a Prime") << endl;
    }
    return 0;
}

 

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值