Pollard-Rho Algorithm简述

Pollard-Rho算法:在期望 O ( n 1 4 ) \mathcal{O}(n^\frac{1}{4}) O(n41)的时间复杂度内分解一个较大的数N的质因数

1.用Miller-Rabin判断该数是否为质数,是则返回;
2.用生日悖论搜索该数的某个因数;
3.对于得到的因子继续调用Pollard-Rho分解其因数.

优化:
在分解质因数时gcd所用次数太多,因为gcd是积性函数,可以将多次所得结果乘起来再一起算gcd。

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define RG register
#define ll long long
using namespace std;
ll n,Ans=0;

ll read()
{
    ll res=0;char ch=getchar();
    while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
    return res;
}
ll print(ll x) {
    if(x>9)print(x/10);
    putchar(x%10+48);
}

ll max(ll a,ll b) { return a>b?a:b; }

ll qm(ll x,ll y,ll p) {
    return (x*y-(ll)((long double)x/p*y)*p+p)%p;
}

ll pw(int a,ll b,ll p)
{
    RG ll ans=1;a%=p;
    for(;b;b>>=1) {
        if(b&1) ans=qm(ans,a,p);
        a=qm(a,a,p);
    }
    return ans;
}

bool MR(int x,ll p)//Miller-Rabin
{
    if(pw(x,p-1,p)!=1) return false;
    RG int k=p-1;
    while(k%2==0)
    {
        k>>=1;
        int t=pw(x,k,p);
        if(t!=1&&t!=p-1) return false;
        if(t==p-1) return true;
    }
    return true;
}

bool check(ll p)
{
    if(p==46856248255981||p<2) return false;
    if(p==2||p==3||p==5||p==61||p==24251) return true;
    return MR(2,p)&&MR(3,p)&&MR(5,p)&&MR(61,p)&&MR(24251,p);
}

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

void Pollard_Rho(ll x)
{
    if(x==1) return;
    if(x%2==0) {
        Ans=max(Ans,2),Pollard_Rho(x/2);
        return;
    }
    if(x%3==0) {
        Ans=max(Ans,3),Pollard_Rho(x/3);
        return;
    }
    if(x%5==0) {
        Ans=max(Ans,5),Pollard_Rho(x/5);
        return;
    }
    if(check(x)) return Ans=max(Ans,x),void();
    RG ll a=7,c=rand(),k=1,s=1;
    RG ll b=(qm(a,a,x)+c)%x;
    RG int p=1;
    while(b!=a&&k==1)
    {
        a=(qm(a,a,x)+c)%x;
		b=(qm(b,b,x)+c)%x,b=(qm(b,b,x)+c)%x;
        ++p;
        if(a!=b) s=qm(s,(b-a),x);
        if(p==127||a==b) k=gcd(x,abs(s)),p=0,s=1;
    }
    Pollard_Rho(k),Pollard_Rho(x/k);
}

int main()
{
    srand(19260817);
    RG int T=read();
    while(T--)
    {
        n=read(),Ans=0;
        Pollard_Rho(n);
        if(Ans==n) printf("Prime");
        else print(Ans); putchar(10);
    }
    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值