ACM入门之【Miller-Rabin素数测试算法】

参考博文:https://blog.csdn.net/forever_dreams/article/details/82314237
模板来自参考博文

这个算法可以大概率的判断一个数是不是质数。时间复杂度是O(T×logN) (T为检测轮数)
这里只列出模板,因为一般不常用。

#include<bits/stdc++.h> 
using namespace std;
typedef long long int LL;
int prime[15]={
    
    2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
LL Quick_Multiply(LL a,LL b,LL c)  //快速积(和快速幂差不多) 
{
    
    
    LL sum=0;
    while(b)
    {
    
    
        if(b&1) sum=(sum+a)%c;
        b>>=1;
        a=(a+a)%c;
    }
    return sum;
}
LL Quick_Power(LL a,LL b,LL c)     //快速幂,这里就不赘述了 
{
    
    
    LL ans=1,res=a;
    while(b)
    {
    
    
        if(b&1) ans=Quick_Multiply(ans,res,c);
        b>>=1;
        res=Quick_Multiply(res,res,c);
    }
    return ans;
}
bool Miller_Rabin(LL x)     //判断素数 
{
    
    
    LL i,j,k;
    LL s=0,t=x-1;
    if(x==2)  return true;   //2是素数 
    if(x<2||!(x&1))  return false;     //如果x是偶数或者是0,1,那它不是素数 
    while(!(t&1))  //将x分解成(2^s)*t的样子 
    {
    
    
        s++;
        t>>=1;
    }
    for(i=0;i<15&&prime[i]<x;++i)      //随便选一个素数进行测试 
    {
    
    
        LL a=prime[i];
        LL b=Quick_Power(a,t,x);      //先算出a^t
        for(j=1;j<=s;++j)    //然后进行s次平方 
        {
    
    
            k=Quick_Multiply(b,b,x);   //求b的平方 
            if(k==1&&b!=1&&b!=x-1)     //用二次探测判断 
              return false;
            b=k;
        }
        if(b!=1)  return false;   //用费马小定律判断 
    }
    return true;   //如果进行多次测试都是对的,那么x就很有可能是素数 
}
int main()
{
    
       
    int t; cin>>t;
    while(t--)
	{
    
    
		LL x; cin>>x;
		if(Miller_Rabin(x)) puts("Yes");//是质数
		else puts("No");
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/124551468