大素数判断和分解

用Miller-Rabin算法进行大素数判断以及Pollard-rho算法进行分解的模版

ll pri[]={2,7,61};//用小素数表做随机种子可避免第一类卡米歇尔数的误判 
/*
if n < 1,373,653, it is enough to test a = 2 and 3;
if n < 9,080,191, it is enough to test a = 31 and 73;
if n < 4,759,123,141, it is enough to test a = 2, 7, and 61;
if n < 1,122,004,669,633, it is enough to test a = 2, 13, 23, and 1662803;
if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11;
if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13;
if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17.
*/
ll ans[100005],flag;//ans数组记录分解质因数的结果,flag记录质因数的个数,相同的质因数不合并! 
ll gcd(ll a,ll b)//非递归,递归的对大数易爆栈
{
        while(b)
        {
                ll c=a%b;
                a=b;
                b=c;
        }
        return a;
} 
ll multi(ll a,ll b,ll n)//乘法快速幂
{
        ll tmp=0;
        while(b){
                if(b&1){
                        tmp+=a;
                        if(tmp>=n)
                                tmp-=n;
                }
                a<<=1;
                if(a>=n)a-=n;
                b>>=1;
        }
        return tmp;
}
ll multimod(ll a,ll m,ll n)//乘方快速幂
{
        ll tmp=1;
        a%=n;
        while(m)
        {
                if(m&1) tmp=multi(tmp,a,n);
                a=multi(a,a,n);
                m>>=1;
        }
        return tmp;
}
bool Miller_Rabin(ll n)//大数判断
{
        if(n<2)
                return false;
        if(n==2)
                return true;
        if(!(n&1))
                return false;
        ll k=0,i,j,m,a;
        m=n-1;
        while(!(m&1)) m>>=1,k++;
        for(i=0;i<3;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;
}
ll pollard_rho(ll c,ll n)//寻找因数
{
        ll 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<<=1;
                x=(multi(x,x,n)+n-c)%n;
        }while(y!=x);
        return n;
}
void rho(ll n)//递归分解
{
        if(Miller_Rabin(n))
    {
        ans[flag]=n;
        flag++;
        return;
    }
        ll t=n;
        while(t>=n)//这一步是找出一个因数并存入t中,注意找出的因数没有任何确定的大小顺序
                t=pollard_rho(rand()%(n-1)+1,n);
        rho(t);
        rho(n/t);
        return;
}
int main()
{
    ll n,i;
    flag=0;//质因数的个数必须初始化 
    scanf("%I64d",&n);
    rho(n);//分解出n的所有质因数存入ans数组 
    for(i=0;i<flag;i++)printf("%I64d ",ans[i]);//显示结果 
    printf("\n");
    return 0;    
} 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值