[筛法]个人对筛法的理解

筛法的引入

首先我们给出一个问题: 1N
最朴素的算法是一一枚举 1N
O(N)O(NN)
那么我们能否做的更好呢?
我们需要的就是筛法

朴素的筛法: Eratosthenes 筛法

由唯一分解定理我们知道,一个合数总是能分解为若干个质数的乘积,因此我们产生这样一个想法:把所有是质数倍数的数都去掉(假如一开始我只知道2是质数),那么剩下的就是质数了。
基于这一想法,我们创造了 Eratosthenes 筛法
代码如下:

memset(check, false, sizeof(check))
int tot = 0;
for (int i = 2; i < N; i++)
    if (! check[i]){
        prime[tot ++] = i;
        for (int j = i * 2; j <= N; j++) check[j] = true;
    }

那么这么做的时间复杂度如何呢?
显然复杂度 T(n)=pnnp=npn1p
那么问题就在于 n
显然这个比调和级数小(即所有数的倒数和),调和级数又比 ln ,所以这至多是一个 O(nlnn) 的算法
具体更为精细的分析, Euler 在他的论文里就指出
pn1p=lnlnn
因此 Eratosthenes 的复杂度是 O(nlnlnn)
注:同样我们可以发现一个数 nloglogn ,我没有发现两者之间的联系,如果有人发现的话请务必告诉我

线性的筛法: Euler 筛法

Euler 基于这样一个想法:每个数只被筛去一次,如果我能做到这一点,那么显然这样的筛法就是 O(n)
具体做法我们先看代码:

memset(check, false, sizeof(check));
int tot = 0;
for (int i = 2; i <= N; i++){
    if (!check[i]) prime[tot++] = i;
    for (int j = 0; j < tot; j++){
        if (i * prime[j] > N) break;
        check[i * prime[j]] = true;
        if (i % prime[j] == 0) break;
    }
}

Euleriprimepjippj<ppjpjipj=ppj|ipjppjip

综上, EulerO(n)

Euler 筛法的应用:求积性函数

定义:
f,a,bf(ab)=f(a)f(b)f
常见积性函数:
欧拉函数 ϕ ,莫比乌斯函数 μ
线性求解:
求积性函数的关键在于求解 f(pk) ,其它时候我们可以直接利用积性求解,而具体的 f(pk)f

你可能感兴趣的:(数学,筛法)