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

原问题 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 False
	return True
该问题全部代码如下:
import math


def 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 True

up_limit = input()
up_limit = int(up_limit)
last_prime, next_prime = 2, 3
count = 0
primes = [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 += 1

print(str(count))
现在,恭喜获得PAT 乙级 1007问题 最后的2分

据说使用C语言只需要LEVEL 1.5的优化即可通过,毕竟两种语言的效率不可比
然而,感谢python,让我们多动脑筋

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值