小工具知识网

当前位置: 首页 > 行业知识 > 判断素数的常见方法

行业知识

判断素数的常见方法

2026-10-18 23:48:34 来源:互联网转载

文章目录

  • ​一、素数的定义
  • 二、素数测试:暴力法
  • 三、暴力法的优化:试除法
  • 四、素数生成:埃氏筛
  • 五、埃氏筛的优化:欧拉筛
    • 欧拉筛的原理
    • 欧拉筛代码示例(C++)
    • 欧拉筛的正确性证明
    • 欧拉筛的线性时间复杂度证明
    • ��、参考资料

      ​一、素数的定义

      素数(Prime number),又称质数,是指在大于1的自然数中,除了1和它自身外,不能被任何其他自然数整除的数叫做质数;否则称为合数。

      值得注意的是,0 与 1 既不是素数,也不是合数。


      二、素数测试:暴力法

      素性测试(Primality test),或素数判定,是检验一个给定的整数是否为素数的测试。

      判断 n n n 是否为素数时,最简单的方式就是暴力法(Brute Force):遍历的所有大于 1 且小于 n n n 的整数,判断 n n n 是否可以被这些数整除,如果不存在可以整除的数,则为素数;否则为合数。

      bool isPrime(int n){    for (int i = 2; i       优点:       简单易懂,完全利用了素数的定义。       缺点:       时间复杂度为                                           O                            (                            n                            )                                  O(n)                     O(n), 当需要判断大量的数时十分缓慢。       如果需要判断从 1 到                                           n                                  n                     n 的的每一个数,则总体时间复杂度为                                           O                            (                                       n                               2                                      )                                  O(n^2)                     O(n2).    

      三、暴力法的优化:试除法

      试除法(Trial Division)中的思想告诉我们,遍历到 n \sqrt{n} n ​即可判断 n n n 是否为素数。

      可以通过反证法证明:

      假设遍历到 n \sqrt{n} n ​仍然无法判断 n n n 是否为素数,则存在自然数 a , b a,b a,b 使得 n = a ⋅ b n = a\cdot b n=a⋅b,同时 a a a 与 b b b 其中之一大于 n \sqrt{n} n ​。

      如果 a a a 与 b b b 其中之一大于 n \sqrt{n} n ​,而另一个小于 n \sqrt{n} n ​,则较小数会在遍历到 n \sqrt{n} n ​前被遍历到,与假设矛盾。

      如果 a a a 与 b b b 皆大于 n \sqrt{n} n ​,则 a ⋅ b > n a\cdot b > n a⋅b>n,与假设矛盾。

      将这一重要性质应用到我们的算法中,可以减少需要遍历的整数数量。在新的算法中,时间复杂度降到了 O ( n ) O(\sqrt{n}) O(n ​)

      bool isPrime(int n){    for (int i = 2; i  // 遍历大于1且小于根号n的整数        if (n % i == 0)        { // 如果n可以被某数整除,则为合数            return false;        }    }    return true; // 遍历结束,则为素数}                                           // 埃氏筛    memset(isPrime, true, sizeof(isPrime)); // 先将所有的数标记为素数    isPrime[0] = false;    isPrime[1] = false; // 0,1皆不是素数    for (int i = 2; i  // 遍历2到根号n的间的所有整数        if (isPrime[i])        { // 如果i为素数,则将它的所有倍数标记            for (int j = i * i; j  // 小于i*i的 i的倍数 已经被之前的素数标记过了,因此可以跳过                isPrime[j] = false;            }        }    }}    memset(isPrime, true, sizeof(isPrime)); // 先将所有的数标记为素数    isPrime[0] = false;    isPrime[1] = false; // 0,1皆不是素数    for (int i = 2; i  // 遍历2到n间的所有整数        if (isPrime[i])            primes[cnt++] = i; // i是素数,那么将i添加到已筛出的素数中,cnt++        for (int j = 0; j 

上一篇:适配各种屏幕尺寸,网页游戏优化秘籍!

下一篇:Win10夜灯模式,深夜的柔和视觉探索