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;
}