Pollar Rho算法

原本是想把这个算法搞懂的,然后在网上看了又看,觉得,还是有时间再来看吧,我错了。

看到了一个大佬的博客,顺带收集一下板子

这个板子可以求大数的最大的因子。

#define LL long long
bool IsPrime(LL);//返回素性测试结果
LL GCD(LL,LL);//返回两个数的GCD
LL Mix(LL,LL,LL);//返回两个数在模运算下的乘积

void MaxFactor(LL n,LL &ans)
{
    if(n==1||n<=ans||IsPrime(n))
    {
    
    	return;//判断特殊情况:n为1或素数
    }
    for(LL c=rand()%(n-1)+1;;c++){
        //为防止随机数无效化,使用死循环
        LL t1=rand()%(n-1)+1,t2=(Mix(t1,t1,n)+c)%n;
        LL p=1,i=0,g=0;
        while(t1!=t2){
            p=Mix(p,abs(t1-t2),n);
            if(!p){//乘积为0时说明找到了一个因子
                g=GCD(n,abs(t1-t2));
                if(g>1&&g<n){
                    MaxFactor(g,ans);
                    MaxFactor(n/g,ans);
                }
                                return;
            }
            ++i;
            if(i==127){//当有127个数时强制测试
                g=GCD(n,p);
                if(g>1&&g<n){
                    MaxFactor(g,ans);
                    MaxFactor(n/g,ans);
                    return;
                }
                p=1,i=0;
            }
            t1=(Mix(t1,t1,n)+c)%n;
            t2=(Mix(t2,t2,n)+c)%n;
            t2=(Mix(t2,t2,n)+c)%n;
        }
        g=GCD(n,p);
        if(g>1&&g<n){//循环退出后收尾
            MaxFactor(g,ans);
            MaxFactor(n/g,ans);
            return;
        }
    }
}

又找了一个板子,这个好像可以求出所有的因子(保存在数组factor中)

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<time.h>
#define times 20
using namespace std;
#define ll long long
ll total;
ll factor[110];
ll qmul(ll a,ll b,ll M){
    a%=M;
    b%=M;
    ll ans=0;
    while (b){
        if (b&1){
            ans=(ans+a)%M;
        }
        a=(a<<=1)%M;
        b>>=1;
    }
    return ans%M;
}///快乘,因为两个longlong的数相乘可能会溢出,所以这里转乘法为加法,思想和快速幂相似
ll qpow(ll a,ll b,ll int M){
    ll ans=1;
    ll k=a;
    while(b){
        if(b&1)ans=qmul(ans,k,M)%M;
        k=qmul(k,k,M)%M;
        b>>=1;
    }
    return ans%M;
}
bool witness(ll a,ll n,ll x,ll sum){
    ll judge=qpow(a,x,n);
    if (judge==n-1||judge==1)return 1;
    while (sum--){
        judge=qmul(judge,judge,n);
        if (judge==n-1)return 1;
    }
    return 0;
}
bool miller(ll n){ ///判断素数
    if (n<2)return 0;
    if (n==2)return 1;
    if ((n&1)==0)return 0;
    ll x=n-1;
    ll sum=0;
    while (x%2==0){
        x>>=1;
        sum++;
    }
    for (ll i=1;i<=times;i++){
        ll a=rand()%(n-1)+1;
        if (!witness(a,n,x,sum))return 0; ///费马小定理的随机数检验
    }
    return 1;
}
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll pollard(ll n,ll c){
    ll x,y,d,i=1,k=2;
    x=rand()%n;
    y=x;
    while (1){
        i++;
        x=(qmul(x,x,n)+c)%n; ///不断调整x
        d=gcd(y-x,n);
        if (d<0)d=-d;
        if (d>1&&d<n)return d; ///找到因子
        if (y==x)return n; ///找到循环,返回n,重新来
        if (i==k){ ///一个优化
            y=x;
            k<<=1;
        }
    }
}
void find(ll n){///寻找这个数的素因子,并存起来
    if (miller(n)){
        factor[++total]=n;
        return ;
    }
    ll p=n;
    while (p>=n) p=pollard(p,rand()%(n-1)+1); ///不断找因子,知道找到为止,返回n说明没找到
    find(n/p);
    find(p);
}
int main(){
    ll n,m,i,t;
    scanf("%lld",&t);
    while (t--){
        scanf("%lld",&n);
        if (miller(n)) printf("Prime\n");
        else {
            memset(factor,0,sizeof(factor));
            total=0;
            find(n);
            sort(factor+1,factor+total+1);
            printf("%lld\n",factor[1]);
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值