基于费马小定理和二次探测定理
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef long long ll;
//快速积取模
ll mm(ll a,ll b,ll mod)
{
ll ans=0;
while(b)
{
if(b&1) ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
//快速幂取模
ll f(ll x,ll n,ll mod)
{
ll ans=1;
while(n)
{
if(n&1) ans=mm(ans,x,mod);
x=mm(x,x,mod);
n>>=1;
}
return ans;
}
//Miller-Rabin素数检测算法
bool miller_rabin(ll n)
{
if(n==2)
return true;
else if(n==1||n%2==0)
return false;
ll u=n-1,t=0;
while(u%2==0) u/=2,t++;//n-1=u*2^t
for(int i=0;i<10;i++)
{
//随机选取一个底数a
ll a=rand()%(n-1)+1;
//计算(a^(n-1))%n=(a^(u*2^t))%n
ll x=f(a,u,n);//先计算(a^u)%n
for(int j=1;j<=t;j++)//再经过t次循环计算得到 ( (a^u)^(2^t) )%n
{
ll y=mm(x,x,n);
if(y==1&&x!=1&&x!=n-1)//如果不满足二次探测定理,则不是素数
return false;
x=y;
}
if(x!=1) return false;//如果不满足费马小定理,则不是素数
}
return true;//是素数
}
int main()
{
int t;
ll n;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
printf("%s\n",miller_rabin(n)?"Yes":"No");
}
return 0;
}