安德里卡的猜想(附代码示例)

133 阅读2分钟

目录

  1. 定义
  2. 算法
  3. 时间复杂度
  4. 一种实现方式

1.定义

猜想是假设的同义词,包括没有证据,尚未被验证为真或假。它从一个真实的事实出发,有一个规则。

素数是一个只能被1和它自己整除的数字。

最初的几个素数是。2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ...

请注意,1并不在这个系列中。

没有一个数学家没有关注过这个独特的数字系列并试图找到2个连续质数的关系。

我们可以首先尝试对它们进行区分,并检查它们之间的差距是如何演变的,我们可以注意到,除了前2个素数的差距是1,是一个奇数外,其余的差距都是偶数。
例如前60个质数的差距:
1,2,2,4,2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,2,10,2,6,6,4,6,6,2,10,2,4,2,12,12,4
,2,4,6,2,10,6,6,6,2,6,4,4,2

你发现这里有什么规律吗?

我试图找到一个,例如4,2,4子集的重复,但系列越多,重复就越少,更大的偶数开始出现。
但这没有太大帮助,因为我们不能像因式或斐波那契数列那样,根据其前辈预测一个n-th素数。

请注意,除了第一个缺口之外,其他的都是偶数。

安德里卡的猜想指出,对于素数的两个连续平方根之间的每一个间隙,其数值都小于1。
andrica-formula-1

2.算法

由于安德里卡猜想是一个使用素数的公式,我们唯一需要实现的是生成素数系列。

如果你是一个编程初学者,如果你想检查一个数字是否是质数,你可能想用一个简单的循环来检查2和它的平方根之间的所有数字!

        loop
            i <- 2..sqrt(n) 
            if (n mod i == 0) return false
        end loop
        return true

这种检查可能会耗费时间和重复检查。因为你从数字2开始检查,一直到达到平方根数。但是在这个子集里,可能还有其他的数字被其他的质数分割,所以没有必要再去检查它们了!

为了避免这种情况,我们可以用一个数组来存储之前检查过的质数,也就是说,我们只把给定的数字除以它之前的质数,这种方法叫做记忆化

procedure isPrime(array p, n)
    i <- 0
    while p[i] <= sqrt(n)
        if (n mod p[i] == 0) return false

    return true

procedure generatePrime(n)
    array p
    j <- 0

    for i <- 3..n-1
        if (isPrime(p, i)) 
            {
            p[j] <- i
            j <- j + 1
            }

另一种方法是使用埃拉托色尼的筛子孙达拉姆的筛子阿特金的筛子

3.时间复杂度

由于我们检查了所有的数字,所以generatePrime函数将是O(N)。
对于isPrime函数,我们只检查N的平方根之前的素数,这取决于素数子集的大小,这意味着通常是O(log N)。
所以,生成素数系列将是O(N logN)

4.一种实现方式

#include <iostream>
#include <math.h>

using namespace std;

bool isPrime(int *p, int n)
{
    int sqrtn = sqrt(n), i=0;
    
    while ( p[i] <= sqrtn )
        if(n%p[i++] == 0) return false; 
    
    return true;
}

int & generatePrime(int n, int &size)
{
    int *p, i, j; 
    p = new int[n];
    
    j=0;
    p[j++]=2;
    
    for (i=3; i < n; i++)
        if(isPrime(p, i)) p[j++] = i;
        
    size = j;   
    
    return *p;
}

void checkAndricaConjecture(int n)
{
    int i=0, size;
    
    int *p = &generatePrime(n,size);

    while (i < size-2)
        cout <<p[i]<<" "<< sqrt(p[i+1]) - sqrt(p[i]) << endl,i++;
}

int main()
{
    int n = 500;
    
    checkAndricaConjecture(n);
    
    return 0;
}

输出。

2 0.317837
3 0.504017
5 0.409683
7 0.670873
11 0.288926
13 0.517554
17 0.235793
19 0.436933
23 0.589333
29 0.1826
31 0.514998
37 0.320362
41 0.154314
43 0.298216
47 0.424455
53 0.401036
59 0.129104
.

..

这些结果可以很容易地放在一个图中来展示启发式行为。
andrica-conjecture-1