问题描述
如果一个正整数只有1和它本身两个约数,则称为一个质数(又称素数)。
前几个质数是:2,3,5,7,11,13……
如果一个质数的所有十进制数位都是质数,我们称它为纯质数。例如:2,3,5,7,23,37都输纯质数,而11,13,17,19,29,31不是纯质数。当然1,4,35也不是纯质数。
请问,在1到20210605中,有多少个纯质数?
答案提交
这是一道结果填空题,你只需要算出结果好提交即可。本体的结果为一个证书,在提交答案时只填写这个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
这里就涉及到质数的算法问题了!
如果这里使用了普通的质数算法问题,就会出现跟我一样的事:算了一个晚上才算出来。
我的算法:
lists = []
for i in range(2, 20210606):
for j in range(2, 20210606):
if i * j <= 20210606:
lists.append(i * j)
else:
break
我的思路:
先把1-20210606中的非质数计算出来,存放到lists中,然后每拿到一个通过了各个位均为质数的算法的数都进行对比,如果这个数没有在lists列表中,则为纯质数。
这样的算法看起来天衣无缝,但是单单是计算lists列表,就要用很久的时间。就算把lists列表计算出来,列表里面也是庞大的数据,也就是说每对比一次,都要把整个lists列表遍历一遍,这甚至需要几秒的时间!这道题最终的结果是1903,计算量极大!也就导致了电脑算了一个晚上~
质数的优化算法:
那么,质数到底要怎么算才能够快?
6!
6是一个神奇的数字,我们按6的倍数来遍历:
对6取余为0:6的倍数
对6取余为2:2的倍数
对6取余为3:3的倍数
对6取余为4:2的倍数
通过上面的分析,除了1,2,3,4,只有对6取余为1和5的数,才有必要计算是否为质数!
就有了下面的算法:
def is_prime(n):
if n == 1 or n == 4:
return False
if n == 2 or n == 3:
return True
if n % 6 == 1 or n % 6 == 5:
# 优化的地方
for i in range(5, int(n**0.5) + 1, 2):
if n % i == 0:
return False
return True
else:
return False
有了这个算法,对于这种运算量巨大的题目,就可以比较轻松化解!
# 判断一个数是否为质数
def is_prime(n):
if n == 1 or n == 4:
return False
if n == 2 or n == 3:
return True
if n % 6 == 1 or n % 6 == 5:
# 优化的地方
for i in range(5, int(n ** 0.5) + 1, 2):
if n % i == 0:
return False
return True
else:
return False
# 判断一个数是否为纯质数
def is_pprime(i):
j = str(i)
for k in j:
if k not in ['2', '3', '5', '7']:
return False
return True
res = 0
# 遍历题目范围中的每个数,依次判断质数与纯质数与否
for num in range(1, 20210605 + 1):
if is_pprime(num) and is_prime(num):
res += 1
print(res)
优化后的算法只需短短十几秒就能算完!