质数筛的应用——等差素数列

题目

2,3,5,7,11,13,.... 是素数序列。 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。

上边的数列公差为 30,长度为 6。

20042004 年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。 这是数论领域一项惊人的成果!

有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:

长度为 10 的等差素数列,其公差最小值是多少?

解析
本题是关于素数的题目,所以第一步就是要学会判断素数的算法。常用的素数判断算法有两种:一种是基于素数定义的枚举法,另一种是筛选法。
基于素数定义的枚举法的思想非常简单,要想判断n是否是素数,只需要从2到n-1枚举是否有数能够被n整除即可。该方法不再赘述,这里重点介绍筛选法。
(1)筛选法
筛选法非常适合求一个整数区间中各数是否是素数的情况,并且区间越大,效率越高。筛选法据说是由古希腊的埃拉托斯特尼(Eratosthenes,约公元前274一公元前194年)发明的,因此又称之为埃拉托斯特尼筛子。
具体做法是:先把N个自然数按次序排列起来,因为1不是质数,也不是合数,所以将1划去,从2开始。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ··· N

第二个数2是质数,保留下来,把2后面所有能被2整除的数都划去。
2 3 5 7 9 11 13 15 17 19 21 ··· N
这时,2后面第一个没被划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。
2 3 5 7 11 13 17 19 ···N
3后面第一个没被划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的数就是不超过N的全部质数。
因为希腊人是把数写在涂蜡的板上的,每划去一个数,就在上面记一个小点,寻求质数的工作完毕后,许多的小点就像一个筛子,所以就把埃拉托斯特尼的方法叫作“埃拉托斯特尼筛子”,简称“筛选法”。
(2)程序的思路
当判断出2~N中的所有素数后,下面便可以采用暴力算法进行枚举。目前有3个不确定的变量:N的范围、公差和素数序列的起始值。
N的范围可以设定成一个常量,需要足够大,以便满足要找的序列。
公差和素数序列的起始值分别设定为两个变量,采用枚举法进行两层循环。循环过程中,判断是否有满足长度为10的等差素数列,如果有,则输出其公差,即是公差最小值。

 

# 筛选质数
N = 10000
lst = [True for _ in range(N)]
for i in range(2, N // 2 + 1):
    if lst[i]:
        for j in range(i + i, N, i):
            lst[j] = False

# 检验等差素数列
def cheak(delta, k):
    for i in range(10):
        if k + i * delta > N - 1:
            return False
        if not lst[k + i * delta]:
            return False
    return True

# 暴搜
for delta in range(2, 500):
    for k in range(2, N):
        if lst[k] and cheak(delta, k):
            print(delta)
            sys.exit(0)

 当然题目中的介绍:存在任意长度的素数等差数列。 这是数论领域一项惊人的成果!

所有小于等差素数列的长度的素数的乘积就是该等差素数列的公差。

运用此知识点可快速求解。

你可能感兴趣的:(算法)