• 三个线性筛法


    写在前面:

      记录了个人的学习过程,同时方便复习

    目录

    • 素数的线性筛法

      有时候需要筛出来一张素数表,即1~n范围内的所有素数

      一个个枚举判断是否为素数显然太慢

      根据[◹]算术基本定理如果存在正整数k(k>2)不是素数,那么它的因子里面一定包含之前的素数

      这样的话,开一个boolean数组标记一下不是素数的数,筛到它们的时候跳过就好

    详见埃拉托斯特尼筛法

      但是如果这样筛,显然会有重复的筛除啊

      比如6筛去了42,7也筛去了42

      这样的情况还有很多很多,十分影响效率,时间上并不是线性的

      但如果按照一个数的最小素因子把这个数排除掉,就没问题了!

      代码如下:

    C++:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int const MAXN=100010;
     6 
     7 int prime[MAXN],tot;
     8 bool notprime[MAXN];
     9 
    10 void pony_prime(int n){ 
    11     notprime[0]=1;
    12     notprime[1]=1;
    13     for(int i=2;i<=n;++i){ 
    14         if(!notprime[i])
    15             prime[tot++]=i;   
    16         for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    17             notprime[i*prime[j]]=1; 
    18             if(i%prime[j]==0) break;
    19         }
    20      }
    21 }
    22 
    23 int main(int argc,char *argv[],char *enc[]){
    24     int m=100;
    25     pony_prime(m);
    26     for(int i=1;i<=m;++i){
    27         if(notprime[i]) printf("%d
    ",i);
    28         else printf("%d    Prime
    ",i);
    29     }
    30     return 0;
    31 }

    Java:

     1 class pony{
     2 
     3     static int MAXN=100010;
     4 
     5     static int[] prime=new int[MAXN];
     6     static int tot=0;
     7     static boolean[] notprime=new boolean[MAXN];
     8 
     9     static void pony_prime(int n){ 
    10         notprime[0]=true;
    11         notprime[1]=true;
    12         for(int i=2;i<=n;++i){
    13             if(!notprime[i])
    14                 prime[tot++]=i;
    15             for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    16                 notprime[i*prime[j]]=true; 
    17                 if(i%prime[j]==0) break;
    18             }
    19          }
    20     }
    21 
    22     public static void main(String[] args) throws Exception {
    23         int m=100;
    24         pony_prime(m);
    25         for(int i=1;i<=m;++i){
    26             if(notprime[i]) System.out.println(i);
    27             else System.out.println(i+" Prime");
    28         }
    29     }
    30 
    31 }
    • 欧拉函数的线性筛法

      [◹]欧拉函数

       欧拉函数有以下五条性质:

      由此,我们可以在素数线性筛的基础上筛出欧拉函数!

      每次想要得到phi[n],详细过程如下:

        若n为素数,根据①,有phi[n]==n-1

        若a*b==n(a,b为任意互质数),根据②,有phi[n]==phi[a]*phi[b],这里的phi[a]和phi[b]都是已经得到的

        若a*p==n(p为质数,且p是a的因数),根据⑤得phi[n]==phi[a]*p

      代码如下:

    C++:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int const MAXN=100010;
     6 
     7 int prime[MAXN],tot;
     8 bool notprime[MAXN];
     9 int euler[MAXN];
    10 
    11 void pony_getPhi(int n){ 
    12     notprime[0]=1;
    13     notprime[1]=1;
    14     euler[1]=1;
    15     for(int i=2;i<=n;++i){ 
    16         if(!notprime[i])
    17         {
    18             prime[tot++]=i;
    19             euler[i]=i-1;//HERE 1
    20         }   
    21         for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    22             notprime[i*prime[j]]=1; 
    23             if(i%prime[j]==0){euler[i*prime[j]]=euler[i]*prime[j];break;}//HERE 5
    24             else euler[i*prime[j]]=euler[i]*euler[prime[j]];//HERE 2
    25         }
    26      }
    27 }
    28 
    29 int main(int argc,char *argv[],char *enc[]){
    30     int m=100;
    31     pony_getPhi(m);
    32     for(int i=1;i<=m;++i){
    33         printf("phi(%d):%d",i,euler[i]);
    34         if(notprime[i]) printf("
    ");
    35         else printf("    [%d]Prime
    ",i);
    36     }
    37     return 0;
    38 }

    Java:

     1 class Pony{
     2 
     3     static int MAXN=100010;
     4 
     5     static int[] prime=new int[MAXN];
     6     static int tot=0;
     7     static boolean[] notprime=new boolean[MAXN];
     8     static int[] euler=new int[MAXN];
     9 
    10     static void pony_getPhi(int n){ 
    11         notprime[0]=true;
    12         notprime[1]=true;
    13         euler[1]=1;
    14         for(int i=2;i<=n;++i){
    15             if(!notprime[i])
    16             {
    17                 prime[tot++]=i;
    18                 euler[i]=i-1;//HERE 1
    19             }
    20             for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    21                 notprime[i*prime[j]]=true; 
    22                 if(i%prime[j]==0){euler[i*prime[j]]=euler[i]*prime[j];break;}//HERE 5
    23                 else euler[i*prime[j]]=euler[i]*euler[prime[j]];//HERE 2
    24             }
    25          }
    26     }
    27 
    28     public static void main(String[] args) throws Exception {
    29         int m=100;
    30         pony_getPhi(m);
    31         for(int i=1;i<=m;++i){
    32             System.out.printf("phi(%d):%d",i,euler[i]);
    33             if(notprime[i]) System.out.println("");
    34             else System.out.println("    ["+i+"]Prime");
    35         }
    36     }
    37 
    38 }
    • 莫比乌斯函数的线性筛法

      莫比乌斯函数μ(d)的定义如下:
        (1)若d=1,那么μ(d)=1 
        (2)若d=p1p2…pk(p1…pk均为互异质数),那么μ(d)=(−1)^k 
        (3)其他情况下,μ(d)=0

      只要抓住定义就能轻松筛出莫比乌斯函数啦

      代码如下:

    C++:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int const MAXN=100010;
     6 
     7 int prime[MAXN],tot;
     8 bool notprime[MAXN];
     9 int miu[MAXN];
    10 
    11 void pony_getMiu(int n){ 
    12     notprime[0]=1;
    13     notprime[1]=1;
    14     miu[1]=1;//HERE 1
    15     for(int i=2;i<=n;++i){ 
    16         if(!notprime[i])
    17         {
    18             prime[tot++]=i;
    19             miu[i]=-1;//HERE 2
    20         }
    21         for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    22             notprime[i*prime[j]]=1; 
    23             if(i%prime[j]==0){miu[i*prime[j]]=0;break;}//HERE 3
    24             else miu[i*prime[j]]=-1*miu[i];//HERE 2
    25         }
    26      }
    27 }
    28 
    29 int main(int argc,char *argv[],char *enc[]){
    30     int m=100;
    31     pony_getMiu(m);
    32     for(int i=1;i<=m;++i){
    33         printf("miu(%d):%d",i,miu[i]);
    34         if(notprime[i]) printf("
    ");
    35         else printf("    [%d]Prime
    ",i);
    36     }
    37     return 0;
    38 }

    Java:

     1 class Pony{
     2 
     3     static int MAXN=100010;
     4 
     5     static int[] prime=new int[MAXN];
     6     static int tot=0;
     7     static boolean[] notprime=new boolean[MAXN];
     8     static int[] miu=new int[MAXN];
     9 
    10     static void pony_getMiu(int n){ 
    11         notprime[0]=true;
    12         notprime[1]=true;
    13         miu[1]=1;//HERE 1
    14         for(int i=2;i<=n;++i){
    15             if(!notprime[i])
    16             {
    17                 prime[tot++]=i;
    18                 miu[i]=-1;//HERE 2
    19             }
    20             for(int j=0; j<tot && i*prime[j]<=n;++j){ 
    21                 notprime[i*prime[j]]=true;
    22                 if(i%prime[j]==0){miu[i*prime[j]]=0;break;}//HERE 3
    23                 else miu[i*prime[j]]=-1*miu[i];//HERE 2
    24             }
    25          }
    26     }
    27 
    28     public static void main(String[] args) throws Exception {
    29         int m=100;
    30         pony_getMiu(m);
    31         for(int i=1;i<=m;++i){
    32             System.out.printf("miu(%d):%d",i,miu[i]);
    33             if(notprime[i]) System.out.println("");
    34             else System.out.println("    ["+i+"]Prime");
    35         }
    36     }
    37 
    38 }

    有木有觉得莫比乌斯函数超级好筛?

  • 相关阅读:
    Markdown学习
    二叉树的最近公共祖先
    javaCompiler简析
    自定义类加载器
    聚合和组合的区别
    拓扑排序
    C++ map和unordered_map
    静态文件加载路径
    文件上传
    jackson
  • 原文地址:https://www.cnblogs.com/Antigonae/p/10127134.html
Copyright © 2020-2023  润新知