zoukankan      html  css  js  c++  java
  • 大数分解,大数判定综合模板

    通过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
    ");
            else
            {
                rhoAll(n);//把大数n分解成质因数
                printf("%I64d
    ",rho(n));//最小的质因数
            }
            for(int i=0;i<flag;i++)//输出这些质因数
                printf("%I64d
    ",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    SHELL[22]
    SHELL[15]
    SHELL[08]
    SHELL[12]
    SHELL[06]
    SHELL[24]
    SHELL[11]
    shell文件合并、去重
    SHELL[25]
    SHELL[14]
  • 原文地址:https://www.cnblogs.com/wt20/p/5762601.html
Copyright © 2011-2022 走看看