Pollard-rho大整数分解

    首先低于一般范围的整数分解,我们可以打一个素数表然后用试除的方法对其进行质因子分解。

    具体实现代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 65555
bool p[N];
int prime[N],num=0;
void init()
{
    memset(p,true,sizeof(p));
    for(int i=2;i<N;i++)
      if(p[i])
      {
          prime[num++]=i;
          for(int j=i+i;j<N;j+=i)
            p[j]=0;
      }
}
int main()
{
    init();
    int n,ans[100];
    while(scanf("%d",&n)!=-1)
    {
        int cnt=0;
        for(int i=0;i<num&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                n/=prime[i];
                ans[cnt++]=prime[i];
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                    ans[cnt++]=prime[i];
                }
            }
        }
        if(n!=1) ans[cnt++]=n;
        for(int i=0;i<cnt-1;i++)
          printf("%d*",ans[i]);
        printf("%d\n",ans[cnt-1]);
    }
    return 0;
}



    

    但如果要对比较大的整数分解,上述方法便失去了实用价值。我们引入Pollard-rho整数分解的方法。

    算法原理:生成两个整数a和b,计算p=gcd(a-b,n),直到p不为1或者a,b出现循环为止,若p=n,则p为质数,否则p为n的一个约数。选取一个小的随机数x1,迭代生成xi=xi-1 ^2+k,一般取k=1,若序列出现循环则退出。计算p=gcd(xi-1 - xi,n),若p=1,返回上一步,直到p>1为止。若p=n,则n为素数,否则p为n的一个约数并递归分解p和n/p.

    实现代码如下:

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <stdio.h>

const int Times = 10;
const int N = 5500;

using namespace std;
typedef long long LL;

LL ct, cnt;
LL fac[N], num[N];

LL gcd(LL a, LL b)
{
    return b? gcd(b, a % b) : a;
}

LL multi(LL a, LL b, LL m)
{
    LL ans = 0;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = (ans + a) % m;
            b--;
        }
        b >>= 1;
        a = (a + a) % m;
    }
    return ans;
}

LL quick_mod(LL a, LL b, LL m)
{
    LL ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = multi(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi(a, a, m);
    }
    return ans;
}

bool Miller_Rabin(LL n)
{
    if(n == 2) return true;
    if(n < 2 || !(n & 1)) return false;
    LL m = n - 1;
    int k = 0;
    while((m & 1) == 0)
    {
        k++;
        m >>= 1;
    }
    for(int i=0; i<Times; i++)
    {
        LL a = rand() % (n - 1) + 1;
        LL x = quick_mod(a, m, n);
        LL y = 0;
        for(int j=0; j<k; j++)
        {
            y = multi(x, x, n);
            if(y == 1 && x != 1 && x != n - 1) return false;
            x = y;
        }
        if(y != 1) return false;
    }
    return true;
}

LL pollard_rho(LL n, LL c)
{
    LL i = 1, k = 2;
    LL x = rand() % (n - 1) + 1;
    LL y = x;
    while(true)
    {
        i++;
        x = (multi(x, x, n) + c) % n;
        LL d = gcd((y - x + n) % n, n);
        if(1 < d && d < n) return d;
        if(y == x) return n;
        if(i == k)
        {
            y = x;
            k <<= 1;
        }
    }
}

void find(LL n, int c)
{
    if(n == 1) return;
    if(Miller_Rabin(n))
    {
        fac[ct++] = n;
        return ;
    }
    LL p = n;
    LL k = c;
    while(p >= n) p = pollard_rho(p, c--);
    find(p, k);
    find(n / p, k);
}

int main()
{
    LL n;
    while(cin>>n)
    {
        ct = 0;
        find(n, 120);
        sort(fac, fac + ct);
        num[0] = 1;
        int k = 1;
        for(int i=1; i<ct; i++)
        {
            if(fac[i] == fac[i-1])
                ++num[k-1];
            else
            {
                num[k] = 1;
                fac[k++] = fac[i];
            }
        }
        cnt = k;
        for(int i=0; i<cnt; i++)
            cout<<fac[i]<<"^"<<num[i]<<" ";
        cout<<endl;
    }
    return 0;
}


你可能感兴趣的:(Pollard-rho大整数分解)