• 数论--素数


    1.素数筛(线筛):

    时间复杂度为O(n),可以筛选出n以内的所有素数,共有tot个,prime[x]==true,则x是素数

    筛选原理:

    任意一个数乘以比它小的素数的结果都是合数

    遇到最小质因子就跳出循环,保证每个合数被其最小质因子筛去

    附上代码:

     1 #include<cstdio>
     2 const int N = 100000 + 5;
     3 bool prime[N];//prime[i]表示i是不是质数
     4 int p[N], tot=0;//p[N]用来存质数,tot为素数的个数
     5 void init(int n){
     6     prime[1]=false;
     7     for(int i = 2; i <=n; i ++) prime[i] = true;//初始化为质数
     8     for(int i = 2; i <=n; i++){
     9         if(prime[i]) p[tot ++] = i;//把质数存起来
    10         for(int j = 0; j < tot && i * p[j] <=n; j++){
    11             prime[i * p[j]] = false;
    12             if(i % p[j] == 0) break;//保证每个合数被它最小的质因数筛去
    13         }
    14     }
    15 }
    16 int main(){
    17     init(11);
    18     for(int i=0;i<tot;i++)
    19     printf("%d
    ",p[i]);
    20     printf("tot=%d
    ",tot);
    21 }

    利用了每个合数必有一个最小素因子。每个合数仅被它的最小素因子筛去正好一次。所以为线性时间。

    2.埃筛--------------埃拉托斯特尼筛法,或者叫埃氏筛法

    原理:

    任意一个素数的倍数都是合数

    过程图解:

    代码也很好写:

     1 #include<cstdio>
     2 const int N = 100000 + 5;
     3 bool prime[N];
     4 void init(){
     5     for(int i = 2; i <= N; i ++) prime[i] = true;
     6     for(int i = 2; i*i <= N; i ++){//判断改成i*i<N 
     7         if(prime[i]){
     8             for(int j = i*i; j <= N; j += i){//从i*i开始就可以了 
     9                 prime[j] = false;  
    10             }
    11         }
    12     }
    13 }
    14 int main(){
    15     init();
    16 }

    时间复杂度为O(n*loglog n),因为loglog n非常小,基本上和线筛无区别,较常用

    (还有个规律,除了2,3,其他的素数一定在6的倍数的旁边,ji

    基于埃筛的原理,我们可以用它干很多事

    3.预处理每个数的所有质因数:

     1 #include<cstdio>
     2 #include<vector>
     3 using namespace std;
     4 const int N = 100000 + 5;
     5 vector<int > prime_factor[N];
     6 void init(){
     7     for(int i = 2; i <= N; i ++){
     8         if(prime_factor[i].size() == 0){//如果i是质数
     9             for(int j = i; j <= N; j += i){
    10                 prime_factor[j].push_back(i);
    11             }
    12         }
    13     }
    14 }
    15 int main(){
    16     init();
    17     for(int i=0;i<prime_factor[60].size();i++)
    18     printf("%d ",prime_factor[60][i]);//60的所有素因子
    19 }

    如果把判断i是质数的判断(第8行),则是预处理每个数的因数

    4.预处理每个数的质因数分解

     1 #include<cstdio>
     2 #include<vector>
     3 using namespace std;
     4 const int N = 100000 + 5;
     5 vector<int > prime_factor[N];
     6 void init(){
     7     int temp;
     8     for(int i = 2; i < N; i ++){
     9         if(prime_factor[i].size() == 0){
    10             for(int j = i; j < N; j += i){
    11                 temp = j;
    12                 while(temp % i == 0){
    13                     prime_factor[j].push_back(i);
    14                     temp /= i;
    15                 }
    16             }
    17         }
    18     }
    19 }
    20 int main(){
    21     init();
    22     for(int i=0;i<prime_factor[60].size();i++)
    23     printf("%d ",prime_factor[60][i]);
    24 }
  • 相关阅读:
    centos 7下安装mysql 5.7.21
    以多主模式优雅进行MGR复制搭建
    JMeter测试工具
    keepalived故障切换邮件通知
    vim常用快捷键
    mysql高可用之MHA--邮件报警
    Shell脚本实现批量下载资源并保留原始路径
    面试常考题 max pool实现
    Cpp 书籍推荐
    面试常考题 浅谈 赛马问题
  • 原文地址:https://www.cnblogs.com/eastblue/p/7617277.html
Copyright © 2020-2023  润新知