【专题】质数筛
发布日期: 2023-08-13 06:36:24 来源: 博客园


(相关资料图)

质数筛

Q:给定自然数 n ,求 [1, n] 区间内的所有质数。

1、原始筛法(时间复杂度:O(n√n)

算法思路:不加思考的暴力枚举,即逐个判断区间内每个数是否是质数。判断单个质数的时间复杂度为O(√n) ,判断 1 ~ n 是否是质数的时间复杂度为O(n√n)

代码展示:

int tot, prime[N]; /* prime[i] 为第 i 个质数 */bool is_prime(int n) {    if (n < 2) return false;    for (int i = 2; i * i <= n; i ++)        if (!(n % i))            return false;    return true;}void prime_sieve() {    for (int i = 1; i <= n; i ++)        if (is_prime(i))            prime[++ tot] = i;}

2、普通筛法(时间复杂度:O(n log n)

算法思路:和原始筛法相比有改进,一个(大于 1)自然数的 k 倍数(k > 1)都一定不是质数。

代码展示:

bool is_prime[N]; /* is_prime[i] 表示 i 是不是质数,false 即是 */int tot, prime[N]; /* 共有 tot 个质数,prime[i] 为第 i 个质数 */ void prime_sieve() {   for (int i = 2; i <= n; i ++){     if (!is_prime[i]) prime[++ tot] = i;     for (int j = i << 1; j <= n; j += i)       is_prime[j] = true;   } }

3、埃氏筛 形式 1(时间复杂度:O(n log logn)

算法思路:著名的质数筛法,由古希腊数学家 Eratosthenes(埃拉托斯特尼)发明,和普通筛法相比减少了许多冗余,一个质数的 k 倍数(k > 1)都一定不是质数。

代码展示:

bool is_prime[N]; /* is_prime[i] 表示 i 是不是质数,false 即是 */int tot, prime[N]; /* tot 个质数,prime[i] 为第 i 个质数 */void Eratosthenes_sieve() {    for (int i = 2; i <= n; i ++){        if (!is_prime[i]){            prime[++ tot] = i;            for (int j = i << 1; j <= n; j += i)                 is_prime[j] = true;        }    }}

4、埃氏筛 形式 2(时间复杂度:O(n log logn)

算法思路:埃氏筛的一种不明显的优化,大于 1 的整数的质数倍数不是质数。

代码展示:

bool is_prime[N]; /* is_prime[i] 表示 i 是不是质数,false 即是 */int tot, prime[N]; /* 共有 tot 个质数,prime[i] 为第 i 个质数 */ void Eratosthenes_sieve() {   for (int i = 2; i <= n; i ++){     if (!is_prime[i]) prime[++ tot] = i;     for (int j = 1; j <= tot && i * prime[j] <= n; j ++)       is_prime[i * prime[j]] = true;   } }

5、欧拉筛(时间复杂度:O(n)

算法思路:最著名、最常用的质数筛!在埃氏筛的形式 2 上多了一行神奇的代码,时间复杂度就从O(nlog logn)降至O(n) ,因其是线性复杂度,所以也称线性筛。如果已经被筛过了,则可以终止这轮筛选合数。

代码展示:

bool is_prime[N]; /* is_prime[i] 表示 i 是不是质数,false 即是 */int tot, prime[N]; /* 共有 tot 个质数,prime[i] 为第 i 个质数 */ void Linear_sieve() {   for (int i = 2; i <= n; i ++){     if (!is_prime[i]) prime[++ tot] = i;     for (int j = 1; j <= tot && i * prime[j] <= n; j ++){      is_prime[i * prime[j]] = true;                 if (!(i % prime[j])) break; // beautiful !!!           }  } }

5、埃氏筛 形式 1 + bitset(时间复杂度:O(n loglogn)

算法思路:令人难以置信的是,埃氏筛搭配 C++ 神奇的 bitset 容器(不是 STL),可以让高复杂度的它效率高于低复杂度的欧拉筛!!!

代码展示:

bitset is_prime; /* is_prime[i] 表示 i 是不是质数,true 即是 */int tot, prime[N]; /* tot 个质数,prime[i] 为第 i 个质数 */void Eratosthenes_sieve() {    is_prime.set(); /* 初始化为 true */    is_prime[0] = is_prime[1] = false;    for (int i = 2; i <= n; i ++){        if (!is_prime[i]){            prime[++ tot] = i;            for (int j = i << 1; j <= n; j += i)                 is_prime[j] = false;        }    }}

参考资料:OI Wiki

关键词:

相关文章

  • 【专题】质数筛

  • 突生变故!欧美2300亿元海上风电开发计划被取消!

  • 威海市环翠区获全省社会救助领域宣传优秀成果

  • 《博德之门3》成为2023年评分最高的游戏

  • 光明助残一心惠民,精心救治重获光明,大叔送上锦旗表感恩

  • 威海市环翠区获全省社会救助领域宣传优秀成果

  • 女足世界杯1/4决赛今天开打,西班牙利矛能否捅破荷兰坚盾

  • 迪马股份罗韶颖:楼市新政若能跟进 下半年市场有望更好

  • 跑步脚踝疼的原因和恢复的方法有哪些 跑步脚踝疼痛的原因

  • 火狐浏览器Firefox原生网页翻译功能来了

  • 苹果计划9月推出四款新iPhone:全部采用三星M12 OLED屏幕

  • 遗传性视神经病变的原因和治疗

  • 杨惠妍卸任增城市碧桂园物业董事长

  • 吉利汽车集团与浙江龙泉市政府合作,聚焦热管理产业

  • 罗德里戈近4场西甲联赛打进4球,比之前27场总进球数还多1球

  • 社保怎么查询缴费记录?这4种方法供你选择

  • 淋巴水肿不用怕,这里教你预防,让你“淋”危不惧,“肿”有办法

  • 《博德之门3》成为2023年评分最高的游戏

  • 《反垄断法》实施十五周年 | 湖北强化竞争政策实施   护航

  • A股被医药"包场"!个股和ETF轮番上攻,就此走出阴霾?机构已在布局

热点图集