PAT乙级练习题_1007“素数对猜想”_python解题

原题

让我们定义 d n d_n ​为: d n = p n + 1 p n d_n=p_{n+1}​​−p_n ,其中 p i p​_i 是第 i i 个素数。显然有 d 1 = 1 d_1=1 ,且对于 n > 1 n>1 d n d_n ​​ 是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数 N(< 1 0 5 10^5 ),请计算不超过 N 的满足猜想的素数对的个数。

输入格式

输入在一行给出正整数N

输出格式

在一行中输出不超过N的满足猜想的素数对的个数。

样例输入

20

样例输出

4

my answer

优化方案:

  1. 从3开始,所有的被判断的数每循环一次+2(步长为2),这样就将所有的偶数排除在外
  2. 利用大于3的素数都满足3n+1或者3n-1(n为正整数),将所有不满足该条件的数筛选掉
  3. 所有的非素数(合数)都可以用几个素数的乘积来表示,故只需用素数作为判断素数时的被除数。所以用一个列表存储“已经被判断为素数的”素数,每一次循环都只从列表中选择小于等于“被判断数开方”的素数。如果在一次循环中,被判断数是素数,就将该数加入到“已经被判断为素数”的素数列表中。
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)
发布了28 篇原创文章 · 获赞 19 · 访问量 5223

猜你喜欢

转载自blog.csdn.net/weixin_43912972/article/details/103947241