首页 > 代码库 > HDU 3864 D_num Miller Rabin 质数判断+Pollard Rho大整数分解

HDU 3864 D_num Miller Rabin 质数判断+Pollard Rho大整数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3864

题意:给出一个数N(1<=N<10^18),如果N只有四个约数,就输出除1外的三个约数。

思路:大数的质因数分解只能用随机算法Miller Rabin和Pollard_rho,在测试多的情况下正确率是由保证的。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
#include <ctype.h>
#include <algorithm>
#include <string>
#include <set>
#include <ctime>
#define PI acos(-1.0)
#define INF 0x7fffffff
#define eps 1e-8
#define maxn 50005
typedef __int64 LL;
typedef unsigned long long ULL;
using namespace std;
LL Factor[100];
int t=0;
LL mul_mod(LL a,LL b,LL n)
{
    a=a%n;
    b=b%n;
    LL s=0;
    while(b)
    {
        if(b&1)
            s=(s+a)%n;
        a=(a<<1)%n;
        b=b>>1;
    }
    return s;
}
LL pow_mod(LL a,LL b,LL n)//求a^b%n
{
    a=a%n;
    LL s=1;
    while(b)
    {
        if(b&1)
            s=mul_mod(s,a,n);
        a=mul_mod(a,a,n);
        b=b>>1;
    }
    return s;
}
bool isPrime(LL n, LL times)
{
    if(n==2)return 1;
    if(n<2||!(n&1))return 0;
    LL a, u=n-1, x, y;
    int t=0;
    while(u%2==0)
    {
        t++;
        u/=2;
    }
    srand(100);
    for(int i=0; i<times; i++)
    {
        a = rand() % (n-1) + 1;
        x = pow_mod(a, u, n);
        for(int j=0; j<t; j++)
        {
            y = mul_mod(x, x, n);
            if ( y == 1 && x != 1 && x != n-1 )
                return false; //must not
            x = y;
        }
        if( y!=1) return false;
    }
    return true;
}
LL gcd(LL a,LL b)
{
    if(a==0) return 1;
    if(a<0) return gcd(-a,b);
    return b==0?a:gcd(b,a%b);
}
LL Pollard_rho(LL n,LL c)//Pollard_rho算法,找出n的因子
{
    LL i=1,j,k=2,x,y,d,p;
    x=rand()%n;
    y=x;
    while(true)
    {
        i++;
        x=(mul_mod(x,x,n)+c)%n;
        if(y==x)return n;
        if(y>x)p=y-x;
        else p=x-y;
        d=gcd(p,n);
        if(d!=1&&d!=n)return d;
        if(i==k)
        {
            y=x;
            k+=k;
        }
    }
}
void factor(LL n)
{
    if(isPrime(n,20))
    {
        Factor[t++]=n;
        return;
    }
    LL p=n;
    while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
    factor(p);
    factor(n/p);
}
void solve(LL a)
{
    if(a==1)
    {
        printf("is not a D_num\n");
        return;
    }
    t=0;
    factor(a);
    sort(Factor,Factor+t);
    if(t==2)
    {
        if(Factor[0]!=Factor[1])
        {
            printf("%I64d %I64d %I64d\n",Factor[0],Factor[1],a);
        }
        else
            printf("is not a D_num\n");
    }
    else if(t==3)
    {
        if(Factor[0]==Factor[1]&&Factor[1]==Factor[2])
            printf("%I64d %I64d %I64d\n",Factor[0],Factor[0]*Factor[1],a);
        else printf("is not a D_num\n");
    }
    else printf("is not a D_num\n");
}
int main()
{
    LL a;
    while(~scanf("%I64d",&a))
    {
        solve(a);
    }
    return 0;
}