目录
积性函数的转移关系
对于当前筛到的正整数 (n) ,若 (fc_n) 表示其最小质因数, (p_i) 表示第 (i) 个因数,我们需要筛的积性函数命名为 (oldsymbol f)
那么,十分显然,对于 (p_i<fc_n) 时, (oldsymbol f(n imes p_i)=oldsymbol f(n)cdot oldsymbol f(p_i))
如果 (oldsymbol f(p_i)) 是一个关于 (p_i) (在对 (m) 取余意义下)的简单有理函数,则上述式子是可求的
简单有理函数可以理解为,简单多项式函数的商。简单多项式即多项式次数,相对筛的线性复杂度,可以视为常数的多项式
由于线性筛过程中会出现 (p_ileq fc_n) ,故我们还需要考虑 (p_i=fc_n) 时的情况:
考虑若 ({oldsymbol f(p^{k+1})over oldsymbol f(p^k)}=g(p),kgeq 1) 为一个关于 (p) 的简单函数,则可以通过
(oldsymbol f(n imes fc_n)=oldsymbol f({nover fc_n^k})cdot oldsymbol f(fc_n^{k+1})=oldsymbol f({nover fc_n^k})cdot g(fc_n)cdot oldsymbol f(fc_n^k)=oldsymbol f(n)cdot g(fc_n))
而快速的求出
故线性筛的条件为:
- (oldsymbol f(p)) 需要为一个关于 (p) 的简单有理函数
- (g(p)={oldsymbol f(p^{k+1})over oldsymbol f(p^k)},kgeq 1) 为一个关于 (p) 的简单函数
则线性筛的效果为:
(oldsymbol f(n imes p)=egin{cases} oldsymbol f(n)cdot oldsymbol f(p),p mid n \ \ oldsymbol f(n)cdot g(p),pmid n end{cases})
线性筛的实现
首先我们需要构造好 (oldsymbol f) 与 (g) ,然后就可以通过上述式子快速实现线性筛了
inline int fp(int p){...}
inline int gp(int p){...}
int fc[MAXN],prime[MAXN],f[MAXN],cntprime;
void sieve(){
f[1]=1;
for(int i=2;i<=lim;i++){
if(fc[i]==0){
fc[i]=i;
prime[++cntprime]=i;
f[i]=fp(i);
}
for(int j=1;prime[j]<fc[i]&&prime[j]*i<=lim;j++){
fc[i*prime[j]]=prime[j];
f[i*prime[j]]=f[i]*f[prime[j]];
}
if(i*fc[i]<=lim){
fc[i*fc[i]]=fc[i];
f[i*fc[i]]=fc[i]*gp(fc[i]);
}
}
}
例如,当我们筛的为 (oldsymbol varphi) 时 (oldsymbol f(p)=p-1,g(p)=p)
筛 (oldsymbol mu) 时 (oldsymbol f(p)=-1,g(p)=0)
当然,后期还有的题目涉及到的积性函数不是常见积性函数,但其若能找到满足上述条件的 (oldsymbol f) 与 (g) ,仍可以用线性筛筛出