Miller-Rabin random method to determine large prime numbers

When testing some very large numbers, it will also consume a lot of time if you use the root number n method to judge. In fact, we have a faster method-Miller-Rabin random method

We know that Fermat's little theorem : If p is a prime number and **(a,p)=1**, then a^(p-1)≡1(mod p) . That is, if p is a prime number, and a and p are relatively prime, then the remainder of a divided by p to the (p-1) power is always equal to 1.

In most cases, the inverse theorem of Fermat's little theorem is valid, then we have a direct application of the theorem. For the number p to be verified, we continue to take a ∈ [1, p-1] and a ∈ Z , verify whether a^(p-1) mod p is equal to 1, if not, then p is definitely not a prime number, taking s times in total. Among them, a^(p-1) mod p can be written in binary by writing p-1, by (a*b)mod c=(a mod c)*b mod c, it can be in t=log(p-1) time Calculate the solution within, if considering the complexity of integer multiplication, the total complexity of one calculation is log³(p-1) . This method is called fast exponentiation modulo.

We also have such a theorem: For 0<x<p, x^2 mod p =1 => x=1 or p-1

We let p-1=(2^t )*u, that is, p-1 is the binary representation of u followed by t zeros. We first calculate x[0]=a^u mod p, and then square t times and modulo p each time. The result of each time is recorded as x[i]. Finally, a^(p-1) mod can also be calculated p. If it is found that x[i]=1 and x[i-1] is not equal to 1 nor p-1, then it is found that p must not be a prime number.

Through the application of these two theorems, the error rate is greatly reduced, and it can be said that there is basically no error.

template:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n;
inline LL mul(LL a,LL b,LL p)//快速乘
{
    
    
    LL ans=0;
    while(b)
    {
    
    
        if(b&1) ans=(ans+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return ans;
}
inline LL poww(LL x,LL num,LL p)//快速幂
{
    
    
    LL sum=1,k=x%p;
    while(num)
    {
    
    
        if(num&1) sum=mul(sum,k,p);
        num=num>>1;
        k=mul(k,k,p);
    }
    return sum;
}
inline bool miller_rabin(long long n)//miller_rabin算法,随机法判断大质数
{
    
    
    if(n==2) return true;
    if(n<2||!(n&1)) return false;
    LL t=0,a,x,y,u=n-1;
    while(!(u&1)) t++,u>>=1;//若u为偶数,则右移一位,用t记录位数
    for(int i=0;i<=20;i++)
    {
    
    
        a=rand()*rand()%(n-1)+1;
        x=poww(a,u,n);
        for(int j=0;j<t;j++)//把移掉的位补回来
        {
    
    
            y=mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1) return false;//二次探测
            x=y;
        }
        if(x!=1) return false;//费马小定理
    }
    return true;
}
int main()
{
    
    
    scanf("%I64d",&n);
    printf("%d",miller_rabin(n));
    system("pause");
    return 0;
}

Guess you like

Origin blog.csdn.net/Stevenwuxu/article/details/112968300