ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

miller_rabin素数判定+Pollard-rho素因子分解

2020-02-22 18:00:13  阅读:277  来源: 互联网

标签:return miller ll Pollard while rho ans mod


一、miller_rabin素数判定
miller_rabin是一种素性测试算法,用来判断一个大数是否是一个质数。miller_rabin是一种随机算法,它有一定概率出错,设测试次数为s,那么出错的概率是 4^(−s)
算法的理论基础:

  1. Fermat定理:若a是任意正整数(1≤ a≤ n−1),n是奇素数,则 a^(n-1) ≡ 1 mod n。
  2. 如果n是一个奇素数,将n−1表示成2^s*r 的形式,r是奇数,a与n是互素的任何随机整数,那么a^r ≡ 1 mod n,或者对某个j (0 ≤ j≤ s−1, j∈Z) 等式a^(2jr) ≡ −1 mod n 成立。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int times = 20;
int number = 0;

map<ll, int>m;
ll Random(ll n)			///生成[0,n]的随机数
{
    return ((double)rand()/RAND_MAX*n+0.5);
}

ll q_mul(ll a,ll b,ll mod) ///快速乘计算 (a*b) % mod
{
    ll ans=0;
    while(b)
    {
        if(b&1)
        {
            b--;
            ans=(ans+a)%mod;
        }
        b/=2;
        a=(a+a)%mod;
    }
    return ans;
}

ll q_pow(ll a,ll b,ll mod) ///快速幂计算 (a^b) % mod
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=q_mul(ans,a,mod);
        b/=2;
        a=q_mul(a,a,mod);
    }
    return ans;
}

bool witness(ll a,ll n )
///miller_rabin算法的主体
///用检验算子a来检验n是不是素数
{
    ll temp=n-1;
    int j=0;
    while(temp%2==0)
    {
        temp/=2;
        j++;
    }
    ///将n-1拆分为a^r*s
    ll x=q_pow(a,temp,n ); ///得到a^r mod n
    if(x==1||x==n-1)
        return true;	///余数为1则为素数
    while(j--) ///否则试验条件2看是否有满足的 j
    {
        x=q_mul(x,x,n);
        if(x==n-1)
            return true;
    }
    return false;
}

bool miller_rabin(ll n)  
///检验n是否是素数
{
    if(n==2)
        return true;
    if(n<2||n%2==0)
        return false;		    ///如果是2则是素数,如果<2或者是>2的偶数则不是素数
    for(int i=1; i<=times; i++) ///做times次随机检验
    {
        ll a=Random(n-2)+1;     ///得到随机检验算子 a
        if(!witness(a,n))		///用a检验n是否是素数
            return false;
    }
    return true;
}


int main( )
{
    ll tar;
    while(cin>>tar)
    {
        if(miller_rabin(tar))	///检验tar是不是素数
            cout<<"Yes, Prime!"<<endl;
        else
            cout<<"No, not prime."<<endl;
    }
    return 0;
}

二、Pollard-rho素因子分解
Pollard-rho素因子分解的时间复杂度是:O(n^1/4)
对于一个大整数n,我们取任意一个数x是n的质因数的几率很小,如果取两个数x1以及x2使得它们的差是n的因数,那么几率就提高了,如果取x1以及x2使得gcd((x1−x2),n)>1的概率就更高了。这就是Pollard-Rho算法的主要思想。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;

ll x[maxn], ans;
queue<ll> aria;

ll multi(ll a, ll b, ll p)	//快速乘
{
    ll ans = 0;
    while(b)
    {
        if(b & 1LL)
            ans = (ans+a)%p;
        a = (a+a)%p;
        b >>= 1;
    }
    return ans;
}

ll qpow(ll a, ll b, ll p)
{
    ll ans = 1;
    while(b)
    {
        if(b & 1LL)
            ans = multi(ans, a, p);
        a = multi(a, a, p);
        b >>= 1;
    }
    return ans;
}

bool miller_rabin(ll n)
{
    if(n == 2)
        return true;
    int s = 20, i, t = 0;
    ll u = n-1;
    while(!(u&1))
    {
        t++;
        u >>= 1;
    }
    while(s--)
    {
        ll a = rand()%(n-2)+2;
        x[0] = qpow(a, u, n);
        for(i = 1; i <= t; i++)
        {
            x[i] = multi(x[i-1], x[i-1], n);
            if(x[i] == 1 && x[i-1] != 1 && x[i-1] != n-1)
                return false;
        }
        if(x[t] != 1)
            return false;
    }
    return true;
}

ll gcd(ll a, ll b)
{
    if(b == 0)
        return a;
    else
        return gcd(b, a%b);
}

ll Pollard_Rho(ll n, int c)
{
    ll i = 1, k = 2, x = rand()%(n-1)+1, y = x;
    while(1)
    {
        i++;
        x = (multi(x, x, n)+c)%n;
        ll p = gcd((y-x+n)%n, n);
        if(p != 1 && p != n)
            return p;
        if(y == x)
            return n;
        if(i == k)
        {
            y = x;
            k <<= 1;
        }
    }
}

void calc(ll n, int c)
{
    if(n == 1)
        return;
    if(miller_rabin(n))
    {
        aria.push(n);
        return;
    }
    ll p = n, k = c;
    while(p >= n)
    {
        p = Pollard_Rho(p, c--);
    }
    calc(p, k);
    calc(n/p, k);
}

int main()
{
    ll n;
    while(~scanf("%lld", &n))
    {
        calc(n, 107);
        cout << aria.front();
        aria.pop();
        while(!aria.empty())
        {
            cout << "*" << aria.front();
            aria.pop();
        }
        cout << endl;
    }
    return 0;
}
爱吃老谈酸菜的DV 发布了317 篇原创文章 · 获赞 105 · 访问量 2万+ 私信 关注

标签:return,miller,ll,Pollard,while,rho,ans,mod
来源: https://blog.csdn.net/weixin_43460224/article/details/104443160

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有