zoukankan      html  css  js  c++  java
  • 三个线性筛法

    写在前面:

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

    目录

    • 素数的线性筛法

      有时候需要筛出来一张素数表,即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 }

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

  • 相关阅读:
    mysql 历史版本下载
    mysql 5.7 版本 You must reset your password using ALTER USER statement before executing this statement报错处理
    5.7 zip 版本的安装 以及遇到的坑
    mysql 5.6zip版本的卸载与5.7 zip 版本的安装
    mysql数据库的备份与还原
    本地Navicat连接docker里的mysql
    docker修改数据库密码
    docker 在push镜像到本地registry出现的500 Internal Server Error
    linux 没有界面内容显示不全解决办法
    json与map互相转换
  • 原文地址:https://www.cnblogs.com/Antigonae/p/10127134.html
Copyright © 2011-2022 走看看