前言

笔主在准备蓝桥杯python的过程中发现大部分的知识点总结都是c++或者java的,于是准备自己写一份python的。


一、埃氏筛法求素数

#埃氏筛法 求n以内的素数个数
n=int(input())
from math import floor
alist=[True]*(n+1)
prime=[]
#由于n以内的合数必然可以被根号n以内的素数筛除掉,所以外层循环的结束是根号n
for i in range(2,floor(int(n)**0.5)+1):
    if alist[i]:
    	prime.append(i)
    	#一般写成i*2也行,但是思考一下会发现小于i的素数的倍数都被筛除了,所以从i*i开始比较合理
        for j in range(i*i,n+1,i):
            alist[j]=False
print(len(prime))

二、例题

1.题目:

求区间[a,b]以内的素数个数

蓝桥杯找素数

【埃氏筛法求素数】_python

2.题解

如果用上面的埃氏筛法,由于右边界可能>10^10,所以会超时。所以先用埃氏筛出右边界R平方根以内的素数,再用R平方根以内所有的素数的倍数去筛除区间[L,R]的合数。最后的答案就是质数个数。

3.代码,有详细注释

#埃氏筛法求素数
from math import floor
alist=[True]*31625
for i in range(2,floor(int(31623)**0.5)+1):
    if alist[i]:
        for j in range(i*i,31623,i):
            alist[j]=False
while True:
    a,b=map(int,input().split())
    isprimeB=[True]*1000001
    for i in range(2,floor(int(b)**0.5)+1):
        if alist[i]:
            j=a//i
            if j*i<a:
            	#确保j*i在[L,R]里,所以需要j+=1
                j+=1
            if j<=1:
            	#如果j为1或者小于1,质数为2,那么可能会把1*2也排除为合数,事实上只有质数的2倍以上的数才是合数。
                j=2
            #将区间[L,R]映射到区间数组[0,R-L]
            for k in range(j*i,b+1,i):
                isprimeB[k-a]=False
    ans=0
    for k in range(0,b-a+1):
        if isprimeB[k]:
            ans+=1
    print(ans)

总结

埃氏筛法的时间复杂度有限,所以记得及时优化代码的时间复杂度。