📅  最后修改于: 2023-12-03 15:07:09.555000             🧑  作者: Mango
分段筛是一种优化算法,通常应用于大质数筛法中,其主要思想是根据质数的性质,对待筛区间进行适当分段,每段内只包含小于等于段内最大数平方根的质数,从而避免冗余计算。
以区间 [1,1000] 为例,分段的具体操作如下:
import math
start = 1
end = 1000
segment = math.isqrt(end) # 取区间终点的平方根作为段内最大值
for i in range(start, end+1, segment):
# 对区间逐段处理
segment_end = min(i+segment-1, end)
print(f"[{i},{segment_end}]")
以上代码执行结果:
[1,31]
[32,62]
[63,93]
[94,100]
其中,以区间终点的平方根作为段内最大值的原因是,如果待筛数值大于段内最大值,则肯定已经被筛过,无需再次计算。
is_prime = [True] * (end+1) # 默认所有数都是质数
is_prime[0] = False # 0和1不是质数
is_prime[1] = False
for i in range(start, end+1, segment):
segment_end = min(i+segment-1, end)
for j in range(2, math.isqrt(segment_end)+1):
# 标记每个段内的质数
if is_prime[j]:
for k in range(max(j*2, (i+j-1)//j*j), segment_end+1, j):
is_prime[k] = False
以上代码会将区间 [1,1000] 内所有质数标记为 True,其余数值标记为 False。
for i in range(start, end+1):
if is_prime[i]:
print(i)
输出结果为区间 [1,1000] 内的所有质数:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
import math
def segmented_sieve(start, end):
segment = math.isqrt(end)
is_prime = [True] * (end+1)
is_prime[0] = False
is_prime[1] = False
for i in range(start, end+1, segment):
segment_end = min(i+segment-1, end)
for j in range(2, math.isqrt(segment_end)+1):
if is_prime[j]:
for k in range(max(j*2, (i+j-1)//j*j), segment_end+1, j):
is_prime[k] = False
primes = []
for i in range(start, end+1):
if is_prime[i]:
primes.append(i)
return primes
if __name__ == '__main__':
start = 1
end = 1000
primes = segmented_sieve(start, end)
print(f"Segmented sieve from {start} to {end}:")
print(primes)
以上代码将输出区间 [1,1000] 内的所有质数:
Segmented sieve from 1 to 1000:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
分段筛是一种优化算法,通常应用于大质数筛法中,其主要思想是根据质数的性质,对待筛区间进行适当分段,每段内只包含小于等于段内最大数平方根的质数,从而避免冗余计算。
以区间 [1,1000] 为例,分段的具体操作如下:
import math
start = 1
end = 1000
segment = math.isqrt(end) # 取区间终点的平方根作为段内最大值
for i in range(start, end+1, segment):
# 对区间逐段处理
segment_end = min(i+segment-1, end)
print(f"[{i},{segment_end}]")
以上代码执行结果:
[1,31]
[32,62]
[63,93]
[94,100]
其中,以区间终点的平方根作为段内最大值的原因是,如果待筛数值大于段内最大值,则肯定已经被筛过,无需再次计算。
is_prime = [True] * (end+1) # 默认所有数都是质数
is_prime[0] = False # 0和1不是质数
is_prime[1] = False
for i in range(start, end+1, segment):
segment_end = min(i+segment-1, end)
for j in range(2, math.isqrt(segment_end)+1):
# 标记每个段内的质数
if is_prime[j]:
for k in range(max(j*2, (i+j-1)//j*j), segment_end+1, j):
is_prime[k] = False
以上代码会将区间 [1,1000] 内所有质数标记为 True,其余数值标记为 False。
for i in range(start, end+1):
if is_prime[i]:
print(i)
输出结果为区间 [1,1000] 内的所有质数:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
import math
def segmented_sieve(start, end):
segment = math.isqrt(end)
is_prime = [True] * (end+1)
is_prime[0] = False
is_prime[1] = False
for i in range(start, end+1, segment):
segment_end = min(i+segment-1, end)
for j in range(2, math.isqrt(segment_end)+1):
if is_prime[j]:
for k in range(max(j*2, (i+j-1)//j*j), segment_end+1, j):
is_prime[k] = False
primes = []
for i in range(start, end+1):
if is_prime[i]:
primes.append(i)
return primes
if __name__ == '__main__':
start = 1
end = 1000
primes = segmented_sieve(start, end)
print(f"Segmented sieve from {start} to {end}:")
print(primes)
以上代码将输出区间 [1,1000] 内的所有质数:
Segmented sieve from 1 to 1000:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]