Prime test (polar Rho decomposition prime factor, Miller Rabin Prime test, POJ[1811])

Article directory

POJ1811

Title (rubbish translation)

describe
Given an integer, you need to determine whether it is a prime.
input
The first line contains the number of test cases t (1<=T<=20) t (1<=T<=20) t (1 < = T < = 20), then the following T lines contain the integer N (2<=N<254) N (2 & lt; = N & lt; 2 ^ {54}) N (2 < = N < 254)
output
For each test case, if N is a Prime number, the line containing the word "Prime" is output; otherwise, the line containing the minimum Prime factor of N is output.
sample input
2
5
10
sample output
Prime
2

thinking

This question uses the Miller Rabin primality test. Point here in Bukit
Pollardpollardpollard? Rhorhorhorho is a random algorithm. Its idea is to first use Miller Miller? Rabinrabinrabin to determine whether the current number is a prime number. If so, record and return. If not, let's set the number to be decomposed as n n n, then we should look for a factor p p p of the current number, find it, and then decompose the prime factor for ppp and n/pn/pn/p respectively, which is similar to but not divide and conquer.
So, how can we quickly find the factor of the current number?
Here, we use the following method: first, we randomly generate two numbers of 1 − n1 - n1 − n, and use the absolute value of these two number differences to compare with nnn to determine whether the absolute value of these two number differences is a factor of nnn.
Here comes another question: why should we use the absolute value of the difference between two random numbers to judge whether it is one of the factors of n, instead of directly generating a random number to judge? Point here in Bukit
Steps:
The definition function f (x) = x 2 + C, ccf(x)=x^2+c, ccf(x)=x2+c, cc are given randomly
Note that since it is in the sense of modulo nnn, the value of xxx will form a ring, similar to ρ ρ
xxx takes one step at a time, yyy takes one step at a time point of 2k2^k2k (the most metaphysical part)
Each time, determine whether gcd(abs(x − y),n)gcd(abs(x − y),n)gcd(abs(x − y),n) is 1
If x=yx=yx=y, exit and random ccc again

Code

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <iostream>
using namespace std;
#define LL long long

LL n, ans, t;

bool flag;

inline LL gcd(LL a, LL b){
    if( !b )
        return a;
    return gcd(b, a%b);
}

inline LL ksc(LL x, LL y, LL mod){
    LL sum = 0;
    while( y ){
        if( y&1 )
            sum = (sum+x)%mod;
        x = (x + x)%mod;
        y >>= 1;
    }
    return sum;
}

inline LL qkp(LL x, LL y, LL mod){
    LL sum = 1;
    while( y ){
        if( y&1 )
            sum = ksc(x,sum,mod);
        x = ksc(x,x,mod);
        y >>= 1;
    }
    return sum;
}

inline bool miller_rabin(LL x){
    if( x == 2 || x == 3 || x == 5 || x == 7 )
        return 1;
    if( x < 2 || x % 2 == 0 )
        return 0;
    LL u, p, xx;
    int k = 0;
    u = x-1;
    while( u%2 == 0 ){
        k++;
        u >>= 1;
    }
    for(int i = 1; i < 11; i ++){
        xx = rand()%(x-1)+1;
        xx = qkp(xx, u, x);
        p = xx;
        for(int j = 1; j <= k; j ++){
            xx = ksc(xx, xx, x);
            if( p != 1 && p != x-1 && xx == 1 )
                return 0;
            p = xx;
        }
        if( xx != 1 )
            return 0;
    }
    return 1;
}

inline LL pollard_rho(LL x, LL c){
    LL i = 1, k = 2;
    LL xx = rand()%x;
    LL y = xx;
    while( 1 ){
        i++;
        xx = (ksc(xx,xx,x)+c)%x;
        LL d = gcd(fabs(y-xx), x);
        if( 1 < d && d < x )
            return d;
        if( y == xx )
            return x;
        if( i == k ){
            y = xx;
            k <<= 1;
        }
    }
}

inline void fin_d(LL x){
    if( miller_rabin(x) ){
        ans = min(ans, x);
        return ;
    }
    LL p = x;
    while( p >= x )
        p = pollard_rho(p, rand()%(x-1)+1);
    fin_d(p);
    fin_d(x/p);
}

signed main(){
    scanf("%lld", &t);
    while( t-- ){
        scanf("%lld",&n);
        ans = 0x3f3f3f3f3f3f3f3f;
        fin_d(n);
        if( n != ans )
            printf("%lld\n", ans);
        else printf("Prime\n");
    }
    return 0;
}

Posted by mc2007 on Mon, 25 Nov 2019 13:56:17 -0800