大数分解,大数判定综合模板

通过poj1811整理这些算法的模板

所有代码如下:

 

#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
#define LL long long
const int maxs = 10000000+5;
//对于1要外加特判,否则会运行错误
//用小素数表做随机种子
__int64 pri[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
__int64 ans[maxs],flag;
//ans数组记录分解质因数的结果(没有顺序),flag记录质因数的个数,相同的质因数不合并!

//最大公约数
__int64 gcd(__int64 a,__int64 b)
{
    while(b!=0)
    {
        __int64 r = a%b;
        a=b;
        b=r;
    }
    return a;
}
//乘法快速幂a*b%n,不写连乘是防止相乘时溢出
__int64 multi(__int64 a,__int64 b,__int64 n)
{
    __int64 temp = 0;
    while(b!=0)
    {
        if(b%2==1)
        {
            temp+=a;
            if(temp>=n)
                temp-=n;
        }
        a*=2;
        if(a>=n)
            a-=n;
        b/=2;
    }
    return temp;
}
//乘方快速幂a^n%m
__int64 multimod(__int64 a,__int64 n,__int64 m)
{
    __int64 ans=1;
    while(n!=0)
    {
        if(n%2==1)
            ans=multi(ans,a,m);
        a=multi(a,a,m);
        n/=2;
    }
    return ans;
}

//判断大数是否为素数(米勒罗宾算法)
//调用multimod(),multi()函数
bool miller_rabin(__int64 n)
{
    if(n<2)
        return false;
    if(n==2)
        return true;
    if(n%2==0)
        return false;
    __int64 k = 0,m,a,i,j;
    m=n-1;
    while(m%2==0)
    {
        m=m/2;
        k++;
    }
    for(i=0;i<10;i++)
    {
        if(pri[i]>=n)
            return true;
        a = multimod(pri[i],m,n);
        if(a==1)
            continue;
        for(j=0;j<k;j++)
        {
            if(a==n-1)
                break;
            a = multi(a,a,n);
        }
        if(j==k)
            return false;
    }
    return true;
}
//寻找因数
__int64 pollard_rho(__int64 c,__int64 n)
{
    __int64 i,x,y,k,d;
    i=1;
    x = y = rand()%n;
    k=2;
    do
    {
        i++;
        d = gcd(n+y-x,n);
        if(d>1&&d<n)
            return d;
        if(i==k)
        {
            y=x;
            k=k*2;
        }
        x = (multi(x,x,n)+n-c)%n;
    }while(y!=x);
    return n;
}
//递归分解,把大整数n分解保存到ans全局数组中,保存的是质因数
//且这些质因数没有保证顺序,也没有排重
void rhoAll(__int64 n)
{
    if(miller_rabin(n))
    {
        ans[flag]=n;
        flag++;
        return;
    }
    __int64 t = n;
    while(t>=n)
    {
        //随机取出一个因子,不一定是素数,也不确定大小
        t = pollard_rho(rand()%(n-1)+1,n);
    }
    rhoAll(t);
    rhoAll(n/t);
    return;
}

//返回大整数n最小的质因数
__int64 rho(__int64 n)
{
    if(miller_rabin(n))
        return n;
    __int64 t = n;
    while(t>=n)
    {
        t = pollard_rho(rand()%(n-1)+1,n);
    }
    __int64 a = rho(t);
    __int64 b = rho(n/t);
    return a<b?a:b;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        flag = 0;
        __int64 n;
        scanf("%I64d",&n);
        if(miller_rabin(n))//是素数
            printf("Prime\n");
        else
        {
            rhoAll(n);//把大数n分解成质因数
            printf("%I64d\n",rho(n));//最小的质因数
        }
        for(int i=0;i<flag;i++)//输出这些质因数
            printf("%I64d\n",ans[i]);
    }
    return 0;
}

 

posted on 2016-08-11 21:11  wastonl  阅读(418)  评论(0编辑  收藏  举报