Miller_Rabin & Pollard_Rho

· · 个人记录

int a[]={0,2,3,5,7,11,13,17,19,23,29,31,37};
int mul(int x,int y,int mod){
    return (__int128)x*y%mod;
}
int ksm(int x,int y,int mod){
    int ans=1;
    while(y){
        if(y&1) ans=mul(ans,x,mod);
        x=mul(x,x,mod),y>>=1;
    }
    return ans;
}
int gcd(int x,int y){
    if(y==0) return x;
    return gcd(y,x%y);
}
int MR(int x){
    if(x<3||x%2==0) return x==2;
    int y=x-1,cnt=0,num;
    while(y%2==0) cnt++,y>>=1;
    for(int i=1;i<=12;i++){
        num=ksm(a[i],y,x);
//      printf("%lld %lld %lld\n",num,y,x);
        if(num==1||num==x-1||num==0) continue;
        for(int j=1;j<=cnt;j++){
            num=mul(num,num,x);
            if(num==x-1&&j!=cnt){
                num=1;break;
            }
            if(num==1) return 0;
        }
//      printf("!!%lld %lld\n",i,num);      
        if(num!=1) return 0;
    }
    return 1;
}
int f(int x,int c,int mod){
    return (mul(x,x,mod)+c)%mod;
}
int PR(int x){
    int s=0,t=0,c=rand()%(x-1)+1;
    for(int len=1,num=1;;len*=2,num=1,s=t){
        for(int i=1;i<=len;i++){
            t=f(t,c,x);
            num=mul(num,abs(t-s),x);
            if(i%127==0){
                int p=gcd(num,x);
                if(p>1) return p;
            }
        }
        int p=gcd(num,x);
        if(p>1) return p;
    }
}
int fenjie(int n){
    if(n==1) return 1;
    if(n<=ans) return ans;
    if(MR(n)) return ans=max(ans,n);
//  printf(":: %lld\n",n);
    int x=n;
    while(x==n) x=PR(n);
    while(n%x==0) n/=x;
    return max(fenjie(x),fenjie(n));
}