题目大意
给两个正整数 N N N( < 1 0 5 <10^5 <105)和 D D D( 1 < D ≤ 10 1<D \leq 10 1<D≤10),判断 N , D N,D N,D是不是翻转质数,翻转质数定义如下:
- N N N是质数
- 将 N N N转成 D D D进制后将其逆序,然后再变成10进制,所得的数也是质数
输入
每组包含几个测试用例,每个测试用例一行有两个整数 N , D N,D N,D,每组最后一行是一个负数
输出
对每个测试用例,如果
N
,
D
N,D
N,D是翻转质数就在一行里输出Yes
,否则在一行里输出No
输入样例
73 10
23 2
23 10
-2
输出样例
Yes
Yes
No
解析
意思很好懂,就是先判断
N
N
N是不是质数,再将
N
N
N转成
D
D
D进制然后逆序再转成10进制,并判断转完之后的数是不是质数,如果都是质数就输出Yes
否则输出No
但是在判断是否是质数的算法上有很多选择:
- 普通的从2遍历到
sqrt(n)
,时间复杂度是O( n \sqrt n n) - 从2到
sqrt(n)
每6个判断一次, 时间复杂度也是O( n \sqrt n n),但是要比上面的那种更快 - Miller-Rabin算法,时间复杂度是O( l o g n logn logn)
为了更快,我选择了Miller-Rabin算法,这个算法要求知道费马小定理,同时会快速幂的算法。所以学这个算法等于学了两个算法+一个定理,太值了
n, d = 0, 0
def trans(n, d): #进制转换
res = list()
while n > 0:
res.append(n % d)
n //= d
tmp = 0
for i in range(len(res)):
tmp *= d
tmp += res[i]
return tmp
def quickPow(a, i, n): #快速幂
if i == 0:
return 1 % n
temp = quickPow(a, i >> 1, n)
temp = temp * temp % n
if i & 1:
temp = temp * a % n
return temp
def test(n, a, d): #Miller-Rabin测试
if n == 2 or n == a:
return True
if (n & 1) == 0:
return False
while not (d & 1):
d >>= 1
t = quickPow(a, d, n)
while d != n - 1 and t != 1 and t != n - 1:
t = t * t % n
d <<= 1
return t == n - 1 or d & 1
def isPrime(n):
if n < 2:
return False
a = [2, 3, 17, 23, 73, 19, 11, 61] #多次进行测试以保证正确率
for i in range(len(a)):
if not test(n, a[i], n - 1):
return False
return True
def solve():
global n, d
while True:
s = list(map(int, input().split()))
if s[0] < 0:
return
n, d = s[0], s[1]
if isPrime(n) and isPrime(trans(n, d)):
print("Yes")
else:
print("No")
if __name__ == "__main__":
solve()