题意:给出p,a问p是不是以a为底的伪素数,如果p不是素数判断,是否a^p%p==a
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
typedef __int64 LL;
LL a,b,sum;
const int S=20;//随机算法判定次数,S越大,判错概率越小
//***************Miller_Rabin 算法进行素数测试***************
int cmp(void const *a,void const *b)
{
if(*(LL *)a>*(LL *)b)
return 1;
else return -1;
}
LL mult_mod(LL a,LL x,LL n)//返回(a*x) mod n,a,x,n<2^63
{
a%=n;x%=n;
LL ret=0;
while(x)
{
if(x&1){ret+=a;if(ret>=n)ret-=n;}
a<<=1;
if(a>=n)a-=n;
x>>=1;
}
return ret;
}
LL pow_mod(LL a,LL x,LL n)//返回a^x mod n
{
if(x==1)return a%n;
int bit[70],k=0;
while(x)
{
bit[k++]=(x&1?1:0);
x>>=1;
}
LL ret=1;
for(--k;k>=0;k--)
{
ret=mult_mod(ret,ret,n);
if(bit[k])ret=mult_mod(ret,a,n);
}
return ret;
}
bool judge(LL a,LL n,LL x,LL t)//以a为基,n-1=x*2^t,检验n是不是合数
{
LL ret=pow_mod(a,x,n),flag=ret;
for(LL i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1&&flag!=1&&flag!=n-1)return true;
flag=ret;
}
if(ret!=1)return true;
return false;
}
bool Miller_Rabin(LL n)
{
if(n==2||n==5||n==7||n==11)return true;
if(n%2==0||n%5==0||n%7==0||n%11==0)return false;
LL x=n-1,t=0;
while((x&1)==0)x>>=1,t++;
bool flag=true;
if(t>=1&&(x&1)==1)
{
for(int i=1;i<=S;i++)
{
LL a=rand()%(n-1)+1;
if(judge(a,n,x,t)){flag=true;break;}
flag=false;
}
}
if(flag)return false;
else return true;
}
int main()
{
int i,j;
LL p,a,b;
while(scanf("%I64d %I64d",&p,&a),p||a)
{
if(Miller_Rabin(p)){printf("no\n");continue;}
b=pow_mod(a,p,p);
if(b==a)
printf("yes\n");
else printf("no\n");
}
return 0;
}