其他分享
首页 > 其他分享> > miller_rabin素数判定+Pollard-rho素因子分解

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

作者:互联网

一、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