#include
<
iostream
>
#include
<
ctime
>
#include
<
cstdlib
>
#include
<
cmath
>
#include
<
algorithm
>
using
namespace
std;
const
int
TIME
=
12
;
//
Miller测试次数
__int64 mod_mult(__int64 a, __int64 b, __int64 n)
//
计算(a*b)%n
{
__int64 s
=
0
;
a
=
a
%
n;
while
(b)
{
if
(b
&
1
)
{
s
+=
a;
s
%=
n;
}
a
=
a
<<
1
;
a
%=
n;
b
=
b
>>
1
;
}
return
s;
}
__int64 mod_exp(__int64 a, __int64 b, __int64 n)
//
计算(a^b)%n
{
__int64 d
=
1
;
a
=
a
%
n;
while
(b
>=
1
)
{
if
(b
&
1
)
d
=
mod_mult(d,a,n);
a
=
mod_mult(a, a, n);
b
=
b
>>
1
;
}
return
d;
}
bool
Wintess(__int64 a, __int64 n)
//
以a为基对n进行Miller测试并实现二次探测
{
__int64 m,x,y;
int
i,j
=
0
;
m
=
n
-
1
;
while
(m
%
2
==
0
)
//
计算(n-1)=m*(2^j)中的j和m,j=0时m=n-1,不断的除以2直至n为奇数
{
m
=
m
>>
1
;
j
++
;
}
x
=
mod_exp(a,m,n);
for
(i
=
1
;i
<=
j;i
++
)
{
y
=
mod_exp(x,
2
,n);
if
((y
==
1
)
&&
(x
!=
1
)
&&
(x
!=
n
-
1
))
//
二次探测
return
true
;
//
返回true时,n是合数
x
=
y;
}
if
(y
!=
1
)
return
true
;
return
false
;
}
bool
miller_rabin(__int64 n,
int
times)
//
对n进行s次的Miller测试
{
__int64 a;
int
i;
if
(n
==
1
)
return
false
;
if
(n
==
2
)
return
true
;
if
(n
%
2
==
0
)
return
false
;
srand(time(NULL));
for
(i
=
1
;i
<=
times;i
++
)
{
a
=
rand()
%
(n
-
1
)
+
1
;
if
(Wintess(a, n))
return
false
;
}
return
true
;
}
int
main()
{
__int64 a,p,tmp;
bool
prime;
while
(scanf(
"
%I64d%I64d
"
,
&
p,
&
a)
!=
EOF)
{
if
(a
==
0
&&
p
==
0
)
break
;
prime
=
miller_rabin(p,TIME);
if
(
!
prime)
//
p不是素数,则判断(a^p)%p=a是否成立
{
tmp
=
mod_exp(a,p,p);
if
(tmp
==
a)
printf(
"
yes\n
"
);
else
printf(
"
no\n
"
);
}
else
printf(
"
no\n
"
);
}
system(
"
pause
"
);
return
0
;
}