PAT 1007. 素数对猜想 python 运行超时问题解决方案

来源:互联网 发布:网络视频广告限制 编辑:程序博客网 时间:2024/06/16 14:42

原问题 https://www.patest.cn/contests/pat-b-practise/1007

让我们定义 dn 为:dn = pn+1 - pn,其中 pi 是第i个素数。显然有 d1=1 且对于n>1有 dn 是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N (< 105),请计算不超过N的满足猜想的素数对的个数。

输入格式:每个测试输入包含1个测试用例,给出正整数N。

输出格式:每个测试用例的输出占一行,不超过N的满足猜想的素数对的个数。

输入样例:
20
输出样例:
4

思路非常简单,一个函数判断某个数是否为质数,主函数从5循环到正整数N即可,关键问题在于判断质数的函数效率如何

以下从低到高说几种质数判断方法(number为待判定的数):

LEVEL 0.  

up_limit = number #以number本身作为循环上限

foriin range(2, up_limit):#尝试从2到number-1的每一个数是否可以被number整除

    if number % i== 0:#余数为零则不是素数            return False    return True
LEVEL 0.5.
    up_limit = int(number/2)  #不用多说吧,最小的除数是2,不可能有大于 number/2 的约数的,顺便取整
LEVEL 1.
    import math
    up_limit = math.sqrt(number)  #从上一级容易想到,约数都是两两一对的,只需要尝试当中一半即可;最合理的是尝试小于其平方根的每个值
LEVEL 2.
   然而,坏消息是即使使用了平方根作为尝试上限,PAT还是会返回 运行超时,自己试试 N=99999 也会发现时间挺长
   优化数据上限的路已经走到头,只能考虑在除数上进行删减筛除,考虑如下问题:
如果一个数 C 能被 (a*b) 整除,那么 C%a 或者 C%b 是多少?
显然,余数都是零,也就是说一个数肯定能被它的约数的约数整除
因此,一切合数作为被除数都是重复劳动
   综上,只需要尝试一个数能否被小于它的平方根的素数整除
   此时可以建立一个素数的数组,被除数只在这个数组中尝试,示例代码如下:
    
up_data = int(math.sqrt(number))  #继续最优化循环上限for prime in primes:  #只尝试素数作为被除数        if prime > up_data:  #循环上限的控制        break        if number % prime == 0:        return Falsereturn True
该问题全部代码如下:
import mathdef is_prime(number, primes):    up_data = int(math.sqrt(number))    for prime in primes:        if prime > up_data:            break        if number % prime == 0:            return False    return Trueup_limit = input()up_limit = int(up_limit)last_prime, next_prime = 2, 3count = 0primes = [2, 3]if up_limit > 4:    for number in range(5, up_limit+1):        if is_prime(number, primes):            primes.append(number)            last_prime = next_prime            next_prime = number            if (next_prime - last_prime) == 2:                count += 1print(str(count))
现在,恭喜获得PAT 乙级 1007问题 最后的2分
据说使用C语言只需要LEVEL 1.5的优化即可通过,毕竟两种语言的效率不可比
然而,感谢python,让我们多动脑筋

原创粉丝点击