【ACM】利用积性函数实现的各种线性筛法

一:线性素数筛
一般的素数筛思路就是选择出小素数,然后划去小素数得到整数倍,这就是”埃拉托斯特尼筛法”,这种方法会同一个元素进行多次筛选。因此有了另一种优化的线性素数筛法。主要思想是:每一个合数都可以进行质因数分解,所以任何一个合数都可以由最小素因子进行唯一标记。

代码如下:

void quick_prime(int n)
{
     memset(prime,0,sizeof(prime));
     int cnt = 0;//用于数组下标累计的计数器
     prime[0] = 1;// 0 和 1不是素数(当然也不是合数)
     prime[1] = 1;
     for(int i=2;i<=n;i++)
     {
          if(!prime[i]) //如果是素数,进行下面的操作
               pri[cnt++] = i;
          for(int j=0 ; j<cnt && i * pri[j] <= maxn ; j++)//遍历现有的素数
          {
                prime[i * pri[j]] = 1;
                if(i % pri[j] ==0)
                       break;//防止反复筛选!
          }
     }
}
  1. prime数组的值代表下标是否为素数,如果为素数,数组的值为0,非素数为1(包括合数和既不是素数也不是合数的数)
  2. pri数组存的是素数,从0开始。
  3. 最主要是break那里,比如12这个数,在普通筛的时候12要被2和3都筛一次,显然这种多余的操作会增加时间复杂度,线性筛中一个数字只被它最小的素因子筛掉,12只被2筛掉,当i等于6的时候2*6==12筛掉12,这时候6%2==0可以break了,如果不break,那么6还会把18筛掉,此时是通过6*3来筛掉18,可是显然18最小的素因子是2,所以当i枚举到9的时候有9*2==18,这样18就又被筛了一次,因此在i等于6的时候不用拿6去筛18,下面用公式来说明:
    当p[j]是i的因子时,设i=p[j]* k,因为素因子从小到大枚举,所以p[j]是i的最小素因子,此时i已经无需再去剔除p[j’] * i (j’>j) 形式的合数了,因为p[j’]* i可以写成p[j’]* (p[j]* k)=p[j](p[j’] k),也就是说所有的p[j’]* i将会被将来的某个i’=p[j’]*k剔除掉,当前的i已经不需要了。
    也就是说如果这时候的i可以被此素数表示,那么下一个素数与i的乘积所得到的结果存在更小的素数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值