【作用】
有时候我们想快速的知道一个数是不是素数,而这个数又特别的大导致 O( 根号n ) 的算法不能通过,这时候我们可以对其进行 Miller-Rabin 素数测试,可以大概率测出其是否为素数。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int prime[10]={2,3,5,7,11,13,17,19,23,29};//取遍30以内的素数,可以保证int范围内的数不会错
int ksc(int a,int b,int c) //快速乘
{
long long ans=0,res=a;
while(b)
{
if(b&1)
ans=(ans+res)%c;
res=(res+res)%c;
b>>=1;
}
return (int)ans;
}
int ksm(int a,int b,int c) //快速幂
{
int ans=1,res=a;
while(b)
{
if(b&1)
ans=ksc(ans,res,c);
res=ksc(res,res,c);
b>>=1;
}
return ans;
}
bool sushu(int x) //判断素数
{
int i,j,k;
int s=0,t=x-1;
if(x==2)
return true; //2是素数
if(x<2||x%2==0)
return false; //如果x是偶数或者是0,1,那它不是素数
while(!(t&1)) //将x分解成(2^s)*t的样子
{
s++;
t>>=1;
}
for(i=0;i<10&&prime[i]<x;i++) //随便选一个素数进行测试
{
int a=prime[i];
int b=ksm(a,t,x); //先算出a^t
for(j=1;j<=s;++j) //然后进行s次平方
{
k=ksc(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 x;
scanf("%d",&x);
if(sushu(x))
printf("Yes\n");
else
printf("No\n");
return 0;
}