zoukankan      html  css  js  c++  java
  • 【数论】埃氏筛法

      这学期的离散数学课程学了一点初等数论,其中的埃氏筛法当时课上没有太懂,课后看了《挑战程序设计竞赛》一书终于弄懂了。(这本书确实很好!算法简洁优美。)

      如果只对一个整数进行素性测试,通常O(√n )的算法就足够了。但如果要对许多整数进行素性测试,则有更为高效的算法,其中就包括埃拉托斯特尼筛法,简称埃氏筛法。它是一个与辗转相除法一样古老的算法,可以用于枚举n以内的素数。

      首先,我们将2到n范围内的所有整数写下来。其中最小的数字2是素数。将表中所有2的倍数都划去。表中剩余的最小数字是3,它不能被更小的数整除,所以是素数。再将表中所有3的倍数都划去。依此类推,如果表中剩余的最小数字是m时,m就是素数。然后将表中所有m的倍数都化去。像这样反复操作,就能依次枚举n以内的素数。

     

    如图所示,最终我们就能得到20以内的所有素数。埃氏筛法的复杂度仅有O(nlognlogn)。对于程序设计竞赛中的数据规模,将它的复杂度看作大致线性的也无妨。下面给出代码: 

     1 #include <iostream>
     2 #include <cstring>
     3 using namespace std;
     4 
     5 //埃氏筛法
     6 
     7 const int MAX_N = 10005;
     8 int prime[MAX_N];  //第i个素数
     9 bool is_prime[MAX_N+1];  //is_prime[i]为true时表示i是素数
    10 
    11 //返回n以内素数的个数
    12 int sieve(int n){
    13     int p = 0;
    14     for(int i = 0; i <= n; i++) is_prime[i] = true;
    15     is_prime[0] = is_prime[1] = false;
    16     for(int i = 2; i <= n; i++){
    17         if(is_prime[i]){
    18             prime[p++] = i;
    19             for(int j = 2*i; j <= n; j+=i) is_prime[j] = false;  //筛去所有素数的倍数
    20         }
    21     }
    22     return p;
    23 }
    24 
    25 
    26 int main()
    27 {
    28     int n;  //枚举n以内素数
    29     while(cin>>n){
    30        int p = sieve(n);
    31         cout<<p<<endl;
    32         for(int i = 0; i < p;i++)
    33             cout<< prime[i]<<" ";
    34         cout<<endl;
    35     }
    36 
    37     return 0;
    38 }
  • 相关阅读:
    昨天是下了一整天的雨,在家里买了一斤肉和恶小白菜吃
    昨天网上感觉好冷,睡在席子上都是感觉打哈欠
    今天是下雨了,看来是要穿长裤上班了
    昨天用的流量有点多60M
    Python常用模块(3)—— shelve、pickle、json、xml、configparser
    Python常用模块(2)—— os、sys、shutil
    Python常用模块(1)—— time、datetime、randrom
    内置函数
    包的导入使用
    模块的导入使用
  • 原文地址:https://www.cnblogs.com/Aikoin/p/10180157.html
Copyright © 2011-2022 走看看