原题
让我们定义
为:
,其中
是第
个素数。显然有
,且对于
有
是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数 N(<
),请计算不超过 N 的满足猜想的素数对的个数。
输入格式
输入在一行给出正整数N
。
输出格式
在一行中输出不超过N
的满足猜想的素数对的个数。
样例输入
20
样例输出
4
my answer
优化方案:
- 从3开始,所有的被判断的数每循环一次+2(步长为2),这样就将所有的偶数排除在外
- 利用大于3的素数都满足
3n+1
或者3n-1
(n为正整数),将所有不满足该条件的数筛选掉 - 所有的非素数(合数)都可以用几个素数的乘积来表示,故只需用素数作为判断素数时的
被除数
。所以用一个列表存储“已经被判断为素数的”素数,每一次循环都只从列表中选择小于等于“被判断数开方”的素数。如果在一次循环中,被判断数是素数,就将该数加入到“已经被判断为素数”的素数列表中。
import math
# 判断是否是素数,是素数就返回True,否则返回False
def is_prime(n, prime_list):
if n < 3:
return n > 1
if n == 3:
prime_list.append(n)
return True
# (优化二)大于3的素数都满足 6n+1 或者 6n-1,所以不满足该条件的一定不是素数
if n % 6 != 1 and n % 6 != 5:
return False
# 素数的因子,只有1和其本身;合数总可以表示成几个质数相乘的形式,即存在小于该合数的素数因子。
# (优化三)所以,在判断是否是素数的时候,被除数只需要从“当前已经被判断为质数”的列表中“小于等于该数的开方”的素数中选择
up_limit = int(math.sqrt(n)) + 1
for i in prime_list:
if i > up_limit:
break
if n % i == 0:
return False
prime_list.append(n)
return True
times = eval(input())
if times == 1 or times == 2:
print(0)
else:
# 当输入的正整数大于2时,定义一个变量用来记录有多少个素数对(初始值为0)
N = 0
# 定义一个变量pre_prime用来存储“当前”最大的素数A,
# 如果发现一个素数B,就与“当前”最大的素数做差(B-A)
# 结果为2,N就加一,“当前”最大素数更新为新的素数的值(A = B)
pre_prime = 2
# 定义一个列表,用来存放已经被判断为素数的数
prime_list = [2]
# (优化一)从3开始,步长为2,这样就将所有的大于3的偶数(一定不是素数)筛选出去了
for i in range(3, times+1, 2):
if is_prime(i, prime_list):
if (i - pre_prime) == 2:
N += 1
pre_prime = i
print(N)