1. 程式人生 > >Miller-Rabin及Pollard-Rho演算法學習小記

Miller-Rabin及Pollard-Rho演算法學習小記

質數快速判斷演算法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); } }