当前位置:   article > 正文

C++的实用工具——筛法

C++的实用工具——筛法

很多c++的算法都有不同的解法,本人精心挑选了最有的解法,今天就来讲一下筛法

埃氏筛

埃氏筛的原理其实很简单,在小学五年级是也会学到这一解法。

步骤

  1. 定义一个bool类型的数组,用数组下标表示哪个数,里面存1和0,1表示是素数,0表示不是素数。
  2. 先把数组全部初始化为1,可以用memset
  3. 从2开始枚举到任意一个数(范围)如果这个数据为1,就说明它是素数,把它的下标的倍数的值全部设为0

代码

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. int count_ss,T;
  4. bool ss[2000005];
  5. void sushu(){
  6. for(int i=2;i<=2000000;i++){
  7. if(ss[i]){
  8. count_ss++;//可以顺便记录一下素数个数
  9. for(int j=i*2;i*j<=2000000;j+=i){
  10. ss[j]=0;
  11. }
  12. }
  13. }
  14. }
  15. signed main(){
  16. memset(ss,1,sizeof(ss));
  17. sushu();
  18. return 0;
  19. }

相关题目

大家可以用埃氏筛做很多题,比如P8319 『JROI-4』分数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

欧拉筛(或线性筛)

线性筛思想: 这个合数只会被它的最大 ( 非自身 ) 的因数(对应最小质因数)筛。 这样能保证每个合数只会被筛一次。
我们发现埃氏筛还是有很多重复的筛过的,例如 30=3*10=2*15 所以我们思考优化筛过的重复的,
通过x=p^{a_1}_{1}*p^{a_2}_2*......*p^{a_n}_n= 最小质因数 * 数字,我们发现我们每个数都有一个最小质因数,假设我们使用他来做数字的标记,我们就可以达到每个数字只被筛选一次。时间复杂度是O(n)

代码

  1. //变量解释:vis[i]为bool类型,表示i是不是素数
  2. //pri[i]为int类型,表示第i个素数
  3. //maxn为筛法范围
  4. void init(){
  5. for (int i=2;i<MAXN;i++){
  6. if(!vis[i]){
  7. pri[++cnt]=i;
  8. }
  9. for(int j=1;j<=cnt;j++) {
  10. if(i*pri[j]>=MAXN)break;
  11. vis[i*pri[j]]=1;
  12. if(i%pri[j]==0){
  13. // i % pri[j] == 0
  14. // 换言之,i 之前被 pri[j] 筛过了
  15. // 由于 pri 里面质数是从小到大的,所以 pri[j]就是 i 的最小质因数,同时也是 i *pri[j] 的最小质因数
  16. // 那么再拿 pri[j + 1] 去筛,pri[j] 是 i * prime[j + 1] 的最小质因数,不符合题目要求
  17. break;
  18. }
  19. }
  20. }
  21. }

相关题目

[传智杯 #4 初赛] 小卡与质数 2 - 洛谷

ps

记得点个关注哦!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/516081
推荐阅读
相关标签
  

闽ICP备14008679号