在筛法中,一个数由它的因子筛出来,因此如果数论函数f(n)与f(x),f(y)有关,其中 x ⋅ y = n x\cdot y=n x⋅y=n,则一般可以通过x、y筛出n的函数值。
在这之中,欧拉筛法中每个数都由其最小质因子筛出,应用范围较广:
定义 L P F ( x ) LPF(x) LPF(x)表示x的最小质因子,欧拉筛法可以求出积性函数,需要:
- 当 p ∈ P , f ( p ) p\in\mathbb{P},f(p) p∈P,f(p)容易求。
- 当积性函数 f f f有: p = L P F ( n ) , n = x ⋅ p p=LPF(n),n=x\cdot p p=LPF(n),n=x⋅p,已知 f ( x ) , f ( p ) f(x),f(p) f(x),f(p),有 p ∣ x p|x p∣x(也就是p与x不互质)时, f ( n ) f(n) f(n)容易求。
其他筛法也可以求一部分积性函数,以下所述筛法,均为欧拉筛。
筛法求欧拉函数
- 对于 p ∈ P , φ ( p ) = p − 1 p\in\mathbb{P},\varphi(p)=p-1 p∈P,φ(p)=p−1。
- 且由欧拉函数的性质4的推论2可知,一个数 p ⋅ x p\cdot x p⋅x的欧拉函数值可以欧拉筛筛出来:
代码如下:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
vector<int> a;
bool vis[105];
int phi[105];
void Euler(int n) {
for(int i=2;i<=n;i++) {
if(!vis[i])
phi[i]=i-1,a.push_back(i);
for(auto&j:a) {
int m=i*j;
if(i*j>100) break;
vis[m]=true;
if(i%j==0) {
phi[m]=j*phi[i];
break;
}
else
phi[m]=phi[i]*phi[j];
}
}
}
int main() {
int n;
cin>>n;
phi[1]=1;
Euler(n);
for(int i=1;i<=n;i++)
cout<<i<<": "<<phi[i]<<endl;
return 0;
}
筛法求莫比乌斯函数
- 对于 p p p, μ ( p ) = − 1 \mu(p)=-1 μ(p)=−1。
- 对于
x
=
i
⋅
j
x=i\cdot j
x=i⋅j,其中
j
j
j是
x
x
x的质因子。
若 i ⊥ j : μ ( x ) = μ ( i ) ⋅ μ ( j ) = − μ ( i ) i\perp j:\mu(x)=\mu(i)\cdot\mu(j)=-\mu(i) i⊥j:μ(x)=μ(i)⋅μ(j)=−μ(i)
否则,x有相同质因子, μ ( x ) = 0 \mu(x)=0 μ(x)=0
因此可以线性筛莫比乌斯函数:
#include<iostream>
#include<vector>
#include<cstdio>
const int N=10000000;
using namespace std;
bool vis[N+5];
int mu[N+5];
vector<int> a;
int pre[N+5];
void Euler() {
mu[1]=1;
for(int i=2;i<=N;i++) {
if(!vis[i])
mu[i]=-1,
a.push_back(i);
for(auto&j:a) {
int x=i*j;
if(x>N) break;
vis[x]=true;
if(i%j==0) break;
mu[x]=-mu[i];
}
}
for(int i=1;i<=N;i++) pre[i]=pre[i-1]+mu[i];
}
using namespace std;
int main() {
Euler();
int n;
cin>>n;
for(int i=1;i<=n;i++)
printf("%d\n",mu[i]);
return 0;
}
线性筛莫比乌斯函数常用于莫比乌斯反演。
线性筛约数个数函数
约数个数函数 σ 0 \sigma_0 σ0用函数 d d d表示
约数个数定理
对于 x x x有标准分解式, x = ∏ i = 1 s p i a i x=\overset{s}{\underset{i=1}\prod}p_i^{a_i} x=i=1∏spiai: d ( x ) = ∏ i = 1 s a i + 1 d(x)=\overset{s}{\underset{i=1}\prod}{a_i+1} d(x)=i=1∏sai+1
这个定理很明显,对于 x x x的质因子 p i p_i pi,可以取 [ 0 , a i ] [0,a_i] [0,ai]个 p i p_i pi,作为 x x x的一个约数的一部分,因此共有 a i + 1 a_i+1 ai+1种可能,应用乘法原理,立即得到上述结论。
线性筛约数个数函数
- d ( p ) = 2 d(p)=2 d(p)=2
- 有
i
⋅
j
=
x
,
j
=
L
P
F
(
x
)
i\cdot j=x,j=LPF(x)
i⋅j=x,j=LPF(x):
i ⊥ j : d 是积性函数, d ( x ) = d ( i ) ⋅ d ( j ) i\perp j:d是积性函数,d(x)=d(i)\cdot d(j) i⊥j:d是积性函数,d(x)=d(i)⋅d(j)
否则:设 f x f_x fx表示 L P F ( x ) LPF(x) LPF(x)的出现次数,则根据约数个数定理:
d ( x ) = ∏ k = 1 s a k + 1 = ( f x + 1 ) ∏ k = 2 s a k + 1 = ( f x + 1 ) ( ( f i + 1 ) ∏ k = 2 s a k + 1 f i + 1 ) = ( f x + 1 ) d ( i ) f i + 1 = d ( i ) f i + 1 ( f x + 1 ) d(x)=\overset{s}{\underset{k=1}\prod}{a_k+1}=(f_x+1)\overset{s}{\underset{k=2}\prod}{a_k+1}=(f_x+1)\left(\frac {\left(f_i+1\right)\overset{s}{\underset{k=2}\prod}{a_k+1}}{f_i+1}\right)=(f_x+1)\frac {d(i)}{f_i+1}=\frac {d(i)}{f_i+1}(f_x+1) d(x)=k=1∏sak+1=(fx+1)k=2∏sak+1=(fx+1) fi+1(fi+1)k=2∏sak+1 =(fx+1)fi+1d(i)=fi+1d(i)(fx+1)
(LPF(x)的出现次数,指LPF(x)在标准分解式中的指数)
因此筛约数个数需要同时维护 f f f、 d d d。 f f f很好维护。
线性筛约数和函数
约数和函数用 σ 1 \sigma_1 σ1表示,这里简写为 σ \sigma σ
约数和定理
对于 x x x有标准分解式, x = ∏ i = 1 s p i a i x=\overset{s}{\underset{i=1}\prod}p_i^{a_i} x=i=1∏spiai: σ ( x ) = ∏ i = 1 s ∑ j = 0 a i p i j \sigma(x)=\overset{s}{\underset{i=1}\prod}{\overset{a_i}{\underset{j=0}\sum}}p_i^j σ(x)=i=1∏sj=0∑aipij
设状态 x i x_i xi表示考虑完前i个质因子,转移到 x i + 1 x_{i+1} xi+1的权值分别为 p i + 1 0 , p i + 1 1 , . . . , p i + 1 a i p_{i+1}^0,p_{i+1}^1,...,p_{i+1}^{a_i} pi+10,pi+11,...,pi+1ai(表示在这个约数中,质因子 p i + 1 p_{i+1} pi+1选取了k次,为 p i + 1 k p_{i+1}^k pi+1k,当然可以不选,权值为1),应用广义乘法原理容易证明。
线性筛约数和函数
- σ ( p ) = p + 1 \sigma(p)=p+1 σ(p)=p+1
- 有
i
⋅
j
=
x
,
j
=
L
P
F
(
x
)
i\cdot j=x,j=LPF(x)
i⋅j=x,j=LPF(x):
i ⊥ j : σ ( x ) = σ ( i ) ⋅ σ ( j ) i\perp j:\sigma(x)=\sigma(i)\cdot\sigma(j) i⊥j:σ(x)=σ(i)⋅σ(j)
否则:设 f x f_x fx表示 L P F ( x ) LPF(x) LPF(x)的出现次数,根据约数和定理:
σ ( x ) = ∏ k = 1 s ∑ x = 0 a k p k x = ∑ k = 0 f x j k ( ∏ k = 2 s ∑ x = 0 a k p k x ) = ∑ k = 0 f x j k ( ∑ x = 0 f i j x ∏ k = 2 s ∑ x = 0 a k p k x ∑ x = 0 f i j x ) = ∑ k = 0 f x j k ( σ ( i ) ∑ k = 0 f i j k ) \sigma(x)=\overset{s}{\underset{k=1}\prod}{\overset{a_k}{\underset{x=0}\sum}}p_k^x={\overset{f_x}{\underset{k=0}\sum}}j^k\left(\overset{s}{\underset{k=2}\prod}\;{\overset{a_k}{\underset{x=0}\sum}}p_k^x\right)={\overset{f_x}{\underset{k=0}\sum}}j^k\left(\frac{{{\overset{f_i}{\underset{x=0}\sum}j^x}}\overset{s}{\underset{k=2}\prod}\;{\overset{a_k}{\underset{x=0}\sum}}p_k^x}{{{\overset{f_i}{\underset{x=0}\sum}j^x}}}\right)={\overset{f_x}{\underset{k=0}\sum}}j^k\left(\frac{\sigma(i)}{{{\overset{f_i}{\underset{k=0}\sum}j^k}}}\right) σ(x)=k=1∏sx=0∑akpkx=k=0∑fxjk(k=2∏sx=0∑akpkx)=k=0∑fxjk x=0∑fijxx=0∑fijxk=2∏sx=0∑akpkx =k=0∑fxjk k=0∑fijkσ(i)
设 g ( n ) g(n) g(n)表示 ∑ k = 0 f n L P F ( n ) k {\overset{f_n}{\underset{k=0}\sum}LPF(n)^k} k=0∑fnLPF(n)k,上式可继续化为: g ( x ) σ ( i ) g ( i ) g(x)\frac {\sigma(i)} {g(i)} g(x)g(i)σ(i)
我们发现 f f f并没有参与计算,因此筛约数和只要同时维护 σ , g \sigma,g σ,g,g很好维护。
筛法求整除函数
整除函数用 σ k \sigma_k σk表示。
整除函数定理
我们注意到 x = ∏ i = 1 s p i a i x=\overset{s}{\underset{i=1}\prod}p_i^{a_i} x=i=1∏spiai,有 x k = ( ∏ i = 1 s p i a i ) k = ∏ i = 1 s p i k ⋅ a i x^k=\left(\overset{s}{\underset{i=1}\prod}p_i^{a_i}\right)^k=\overset{s}{\underset{i=1}\prod}p_i^{k\cdot a_i} xk=(i=1∏spiai)k=i=1∏spik⋅ai,因此对于每个数的贡献,可以拆开成它的质因子的k次幂来算。
- 对于 x x x有标准分解式, x = ∏ i = 1 s p i a i x=\overset{s}{\underset{i=1}\prod}p_i^{a_i} x=i=1∏spiai: σ k ( x ) = ∏ i = 1 s ∑ j = 0 a i p i k ⋅ j \sigma_k(x)=\overset{s}{\underset{i=1}\prod}\;{\overset{a_i}{\underset{j=0}\sum}}p_i^{k\cdot j} σk(x)=i=1∏sj=0∑aipik⋅j
设状态 x i x_i xi表示考虑完前i个质因子,在这个约数中,下一个质因子选取了c次,就是 p i + 1 c p_{i+1}^c pi+1c,转移到 x i + 1 x_{i+1} xi+1的权值为 ( p i + 1 c ) k \left(p_{i+1}^c\right)^k (pi+1c)k,不选权值为1,应用广义乘法原理容易证明。
整除函数定理是约数和定理、约数个数定理的一般情况。
筛法求整除函数
- σ k ( p ) = p k + 1 \sigma_k(p)=p^k+1 σk(p)=pk+1
- 有
i
⋅
j
=
x
,
j
=
L
P
F
(
x
)
i\cdot j=x,j=LPF(x)
i⋅j=x,j=LPF(x):
i ⊥ j : σ ( x ) = σ ( i ) ⋅ σ ( j ) i\perp j:\sigma(x)=\sigma(i)\cdot\sigma(j) i⊥j:σ(x)=σ(i)⋅σ(j)
否则:设 g ( X ) = ∑ i = 0 L P F ( X ) 的出现次数 L P F ( x ) k ⋅ i g(X)=\overset{LPF(X)的出现次数}{\underset{i=0}\sum }LPF(x)^{k\cdot i} g(X)=i=0∑LPF(X)的出现次数LPF(x)k⋅i:
σ k ( x ) = ∏ i = 1 s ∑ j = 0 a i p i k ⋅ j = g ( x ) ∏ i = 2 s ∑ j = 0 a i p i k ⋅ j = g ( x ) ( g ( i ) ∏ i = 2 s ∑ j = 0 a i p i k ⋅ j g ( i ) ) = g ( x ) ⋅ σ k ( i ) g ( i ) \sigma_k(x)=\overset{s}{\underset{i=1}\prod}\;{\overset{a_i}{\underset{j=0}\sum}}p_i^{k\cdot j}=g(x)\overset{s}{\underset{i=2}\prod}\;{\overset{a_i}{\underset{j=0}\sum}}p_i^{k\cdot j}=g(x)\left(\frac{g(i)\overset{s}{\underset{i=2}\prod}\;{\overset{a_i}{\underset{j=0}\sum}}p_i^{k\cdot j}}{g(i)}\right)=g(x)\cdot\frac{\sigma_k(i)}{g(i)} σk(x)=i=1∏sj=0∑aipik⋅j=g(x)i=2∏sj=0∑aipik⋅j=g(x) g(i)g(i)i=2∏sj=0∑aipik⋅j =g(x)⋅g(i)σk(i)
筛法求整除函数需要同时维护 g , σ k g,\sigma_k g,σk。 g g g很容易维护。
后记
于是皆大欢喜。