Miller-Rabin及Pollard-Rho演算法學習小記
阿新 • • 發佈:2019-01-02
質數快速判斷演算法Miller-Rabin
不想詳細寫了,因為也不會證。
貼板子!
bool Miller_Rabin(ll n){
if (n==1) return 0;
int s=5,t=0,i;
ll a,p,k=n-1;
while (k%2==0) k/=2,t++;
while (s--){
a=random(n-1)+1;
p=a=qsm(a,k,n);
fo(i,1,t){
a=mul(a,a,n);
if (a==1&&p!=1 &&p!=n-1) return 0;
p=a;
}
if (a!=1) return 0;
}
return 1;
}
因數快速分解演算法Pollard-Rho
不想詳細寫了,因為也不會證。
貼板子!
ll Pollard_Rho(ll n){
ll k,x,y,c,d,i=1;
while (1){
c=random(n-1);
k=2;y=x=random(n);
i=1;
while (1){
y=(mul(y,y,n)+c)%n;
d=gcd(abs (x-y),n);
if (i==k) x=y,k<<=1;
i++;
if (d!=1) break;
}
if (d!=n) return d;
}
}
BZOJ3667
裸題
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
int i,j,k,l,t,m,ca;
ll n,ans;
ll random(ll x){
ll t=rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
return t%x;
}
ll mul(ll a,ll b,ll p){
ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
return tmp<0?tmp+p:(tmp>=mo?tmp-mo:tmp);
}
ll qsm(ll x,ll y,ll mo){
if (!y) return 1;
ll t=qsm(x,y/2,mo);
t=mul(t,t,mo);
if (y%2) t=mul(t,x,mo);
return t;
}
bool Miller_Rabin(ll n){
if (n==1) return 0;
int s=5,t=0,i;
ll a,p,k=n-1;
while (k%2==0) k/=2,t++;
while (s--){
a=random(n-1)+1;
p=a=qsm(a,k,n);
fo(i,1,t){
a=mul(a,a,n);
if (a==1&&p!=1&&p!=n-1) return 0;
p=a;
}
if (a!=1) return 0;
}
return 1;
}
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll Pollard_Rho(ll n){
ll k,x,y,c,d,i=1;
while (1){
c=random(n-1);
k=2;y=x=random(n);
i=1;
while (1){
y=(mul(y,y,n)+c)%n;
d=gcd(abs(x-y),n);
if (i==k) x=y,k<<=1;
i++;
if (d!=1) break;
}
if (d!=n) return d;
}
}
void work(ll n){
if (Miller_Rabin(n)){
ans=max(ans,n);
return;
}
ll p=Pollard_Rho(n);
ll q=n/p;
work(p);work(q);
}
int main(){
srand(19890604);
scanf("%d",&ca);
while (ca--){
scanf("%lld",&n);
ans=0;
work(n);
if (ans==n) printf("Prime\n");else printf("%lld\n",ans);
}
}