zoukankan      html  css  js  c++  java
  • 线性筛

    定义:

    线性筛是在O(nlog(log(n)))的Eratosthenes筛法基础上改进得到的一种算法,可以O(n)求得1~n中的所有素数,因此经常在一些与素数有关的问题中用于预处理。对线性筛进行扩展之后,又可以计算出几乎所有的积性函数。

    PS:素数密度据一位老师所说是O(n/ln(n))的。

    原理:

    线性筛的基础思想与Eratosthenes筛法相同,不再赘述。Eratosthenes筛法在运行过程中,含有多个质因子的数会被重复筛掉。例:30=2*3*5,则它会被2,3,5都筛一遍,而这显然是没有必要的。线性筛正是从这个地方着手改进得来。

    线性筛的核心思想就是在筛的过程中,每个合数都只被它的最小质因子筛去。这样就能保证每个合数都只被筛一次,复杂度为O(n)。

    下面是线性筛的代码:

    void prime()
    {
       int i,j;
       p[1]=1;
       for(i=2;i<=n;i++)
       {
          if(!p[i]){b[++tot]=i;}
          for(j=1;j<=tot&&i*b[j]<=n;j++)
          {
             p[i*b[j]]=1;
             if(i%b[j]==0){break;}
          }
       }
    }

    可以发现,线性筛与Eratosthenes筛的区别仅仅是多了一条语句。下面来证明这条语句能使每个合数都只被它的最小质因子筛去。

    证明:由p[i*b[j]]=1;又由每个合数都只被它的最小质因子筛去可知,b[j]是i*b[j]的最小质因子。又因为b数组是单调增的,如果i中有b[j]这个质因子,则b[j+1],b[j+2]......一定都不是i*b[j+1],i*b[j+2],......的最小质因子,因此在i基础上的筛没有必要进行下去,直接跳出循环。

    至此,我们便实现了O(n)筛出1~n的所有素数。

    例题:

    Luogu P3383 【模板】线性筛素数 题目链接

    题解:

    线性筛裸题,直接使用即可。这道题用Eratosthenes筛也可以过,但速度差异明显。

    扩展:积性函数的计算

    定义:

    对于一个数论函数f(x),gcd(a,b)=1,如果有f(a*b)=f(a)*f(b),则称f(x)具有积性。

    常见的积性函数:欧拉函数φ,莫比乌斯函数μ,约数幂次和dk. ,gcd(n,k)(k为给定整数)

    原理:

    在原有线性筛中额外求一个数组h,h[i]表示i的最小质因子的幂次。即:x=p1a1+p2a2+......,(ai!=0,p1<p2<......)则h[x]=p1a1

    在线性筛结束之后,从1~n线性递推,由gcd(h[i],i/h[i])=1,f(i)=f(h[i])*f(i/h[i])。

    当i=pk 时需要特殊处理,一般从该积性函数的定义就可以直接计算。例:φ(pk )=p-pk-1

    至此,我们便实现了线性筛的扩展。

    代码(线性筛求φ):

    #define LL long long

    void prime()
    {
       LL i,j,k;
       p[1]=1;phi[1]=1;
       for(i=2;i<maxn;i++)
       {
          if(!p[i]){b[++tot]=i;h[i]=i;}
          for(j=1;j<=tot&&i*b[j]<maxn;j++)
          {
             p[i*b[j]]=1;h[i*b[j]]=b[j];
             if(i%b[j]==0){h[i*b[j]]=h[i]*b[j];break;}
          }
       }
       for(i=1;i<=tot;i++){for(j=b[i];j<maxn;j*=b[i]){phi[j]=j-j/b[i];}}
       for(i=2;i<maxn;i++){phi[i]=phi[h[i]]*phi[i/h[i]];}
    }

  • 相关阅读:
    Spring事务的一些基本知识(一)
    Redis管道
    Spring事务的一些基本知识(四)大事务的危害与优化
    登录页面测试点
    朋友圈点赞用例的设计点
    面向对象
    函数的重载
    构造代码块和静态代码块,构造函数的执行
    单例设计模式
    三分查找(2020icp南京F)
  • 原文地址:https://www.cnblogs.com/XSC637/p/7424778.html
Copyright © 2011-2022 走看看