SIEVE 线性筛

Posted miracevin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SIEVE 线性筛相关的知识,希望对你有一定的参考价值。

今天来玩玩筛

英文:Sieve

有什么筛?

这里介绍:素数筛,欧拉筛,莫比乌斯筛,约数个数筛

为什么要用筛?

顾名思义,筛就是要漏掉没用的,留下有用的。最终筛出来1~n的数的一些信息。

为什么要用线性筛?

考虑最基础的线性筛素数,是O(n)的。

而一般的做法是:

1.对于每个m暴力枚举1~sqrt(m)看能否被整除。O(nsqrt(n))

2.对于每个找到的素数,用它去将所有它的倍数的数都干掉。O(nlogn)

但是,即使是第二种,也有一个log

这是因为一个合数会被它的所有质因子筛一次。要重复质因子个数次,除第一次之外都没用。

所以用线性筛

 

线性筛原理:

一个算法,使得每个合数只被它的最小质因子筛一次。

怎么保证呢?

 

素数线性筛:

先看代码:

#include<bits/stdc++.h>
using namespace std;
const int N=10000000+10;
int ps[N],cnt;
bool v[N];
int n,m;
void sieve(){
    for(int i=2;i<=n;i++){
        if(v[i]==0){
            ps[++cnt]=i;
        }
        for(int j=1;j<=cnt;j++){
            if(i*ps[j]>n) break;
            v[i*ps[j]]=1;
            if(i%ps[j]==0) break;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    sieve();
    v[1]=1;
    int t;
    for(int i=1;i<=m;i++){
        scanf("%d",&t);
        if(v[t]) printf("No
");
        else puts("Yes");
    }
    return 0;
}

看不懂...................

解释:
对于一个质数,之前没有被标记。肯定只会有一次查到。把它记录到素数集合里去。

然后,不论这个数是否为质数,都将已有的质数从1~cnt循环一遍,把所有的i*ps[j]标记。

当i*ps>n break,可以理解。

当i%ps==0 break.???

这个时候,ps和i不互质了,而ps第一次整除i,所以ps就是i的最小质因数。叫他ps0

而之后,ps更大,ps*i的最小质因数就不是ps了。因为i里有ps0,这个合数就等着以后i更大了,通过ps0筛掉。

ps再大,后面的ps*i的最小质因数都不是ps,所以之前直接break掉就好。

由于每个合数只会被i*ps的形式找到一次。而内层循环每一次都对应一个将v[ps*i]=1的操作。

所以内层循环均摊O(1),总共O(n)

完毕。

 

欧拉线性筛:

代码:fai(i) 1~i中和i互质的数的个数。

可以容斥推出公式:假设:i=p1^q1*p2^q2*....pn^qn

那么,fai(i)=p1^(q1-1)*(p1-1) * p2^(q2-1)*(p2-1) * ......pn^(qn-1) * (pn-1)

证明不是本篇想讲的。

void sieve(){
    for(int i=2;i<=n;i++){
        if(v[i]==0){
            fai[i]=i-1;
            pri[++cnt]=i;
        }
        for(int j=1;j<=cnt;j++){
            if(i*pri[j]>n) break;
            v[i*pri[j]]=1;
            if(i%pri[j]==0) {
                fai[i*pri[j]]=fai[i]*pri[j];break;
            }
            else{
                fai[i*pri[j]]=fai[i]*(pri[j]-1);
            }
        }
    }
}

并不想从积性函数性质入手解释。

显然的,当处理到fai[i]的时候,i的值应该就知道了。i是质数就现成赋值。

考虑公式。

当i%ps==0 时,i的质因子中有ps,那么i*ps的质因子ps的次数就大于一,那么,就是fai[i]*ps了

否则,i*ps 的 ps的次数就是1,那么,ps^(1-1)*(ps-1)=(ps-1) 所以是fai[i]*(ps-1)

之后的各种操作基于线性筛的要求和特质。(即每个数只被它的最小质因子筛一次)

例题:SDOI2008 仪仗队

 


以上是关于SIEVE 线性筛的主要内容,如果未能解决你的问题,请参考以下文章

线性筛

线性筛-三合一,强大O(n)

莫比乌斯反演

你好 数论(未完待续)

埃拉托色尼的分段筛?

Eratosthenes筛