质数的两种筛法

目录

目录地址

质数的朴素筛法

根据定义,我们不难得出,如果要知道 \(1\)~\(n\) 范围内的所有质数,我们只需要从 \(2\)\(n\) 开始枚举,再判断是否是质数即可:

bool isprime[MAXN];
for(int i=2;i<=n;i++){
    isprime[i]=1;
    for(int j=2;j*j<=i;j++){
        if(i%j==0){
            isprime[i]=0;
            break;
        }
    }
}

当枚举到的数为 \(n\) 的时候,内层的复杂度是 \(O(\sqrt n)\) 的,而外层 \(O(n)\) 枚举

因此,很多人觉得是 \(O(n\sqrt n)\)

其实,本人对此持怀疑态度:本人认为只有 \(o(n\sqrt n)\)

首先:每个合数都是被自己的最小质因子筛到,而每个质数 \(p\) 花费的时间是 \(O(\sqrt p)\)

质数的很显然,对于合数的,我们用反证法:如果这个数 \(m\) 的最小质因数为 \(fc\) ,它被判定为合数时 \(i=k\)

因此, \(m\) 应该在 \(k\) 之前都不能退出循环

而如果 \(fc\)\(k\) 的因数,\(fc<k\)(因为 \(k\) 为合数);如果不为的话, \(k\) 的最小质因数假设为 \(fc'\)\(fc<fc'<k\)

因此, \(m\)\(fc\) 时就一定退出了

综上,复杂度其实并没有达到 \(O(n\sqrt n)\) ,其实复杂度是更小的

优化

我们考虑每个合数,一定是被它的最小质因数筛到。而一个数 \(n\) 的最小质因数 \(fc\) ,一定有 \(fc\in Prime,fc\leq n\)

所以,我们把之前筛到的所有质数存起来,依次判断是不是这个数的因数就行了

bool isprime[MAXN];
int prime[MAXN]={2},cntprime=1;
for(int i=3;i<=n;i++){
    isprime[i]=1;
    for(int j=1;prime[j]*prime[j]<=i;j++){
        if(i%prime[j]==0){
            isprime[i]=0;
            break;
        }
    }
    if(isprime[i]==1){
        prime[cntprime++]=i;
    }
}

因为 \(1\)~\(n\) 的质数个数约等于 \(n\over\ln n\) (我们假定特殊化处理:\(\ln 1=1\)

所以复杂度为 \(\displaystyle T(n)=\sum_{i=1}^n {\sqrt{i}\over \ln \sqrt{i}}=2\sum_{i=1}^n{\sqrt{i}\over \ln i}\)

可以证明,复杂度 \(T(n)\) 与变上限函数 \(\displaystyle \int_a^n {\sqrt{i}\over\ln i}\text di\) 是同阶的

不过很可惜,这玩意儿的积分我不会,不过我们可以发现:当 \(n\) 足够大时,一定会满足下面不等式:

\({\text d\over \text di}(i\ln\ln i)=\ln\ln i+{1\over \ln i}\leq {\sqrt i\over \ln i}\leq \ln i+1= {\text d\over \text di}(i\ln i)\leq {3\over 2}\sqrt i={\text d\over \text di}(i\sqrt i)\)

因此 \(\displaystyle n\ln\ln n\leq \int_a^n{\sqrt i\over \ln i}\text di\leq n\ln n\leq n\sqrt n\)

所以,我们可以说,这个方法肯定是更优的,复杂度是 \(o(n\log n)\) 的,但因为同时也是 \(\omega(n\log\log n)\)

猜你喜欢

转载自www.cnblogs.com/JustinRochester/p/12335779.html