积性函数筛法(1)_算法
JueFan 一只绝帆

积性函数筛法(1)

本文来介绍一些基础性概念,为后文服务。

可能适合于已经会一点点下述内容的人来看,可能会增进你的理解。

  • 积性函数
    • 概念
    • Dirichlet\rm Dirichlet 卷积
    • 常见积性函数
  • 线性筛
    • 线性筛素数/求普通积性函数
    • 线性筛 Dirichlet\rm Dirichlet 卷积/任意积性函数
  • 整除分块
    • 普通整除分块
    • 多限制整除分块
    • 平方整除分块
    • 整除分块的常数优化:Dirichlet\rm Dirichlet 双曲线法
  • 莫比乌斯反演
    • 概念
    • 欧拉反演
    • 偏序集上的莫比乌斯反演
  • 例题

积性函数

概念

我们把 f:N+Rf:\mathbb N^+\to \mathbb R 的函数 ff 称为 数论函数,其中 R\mathbb R 为交换环,应用中的数论函数一般定义域为 N+\mathbb N^+,值域为 Z\mathbb Z

满足 a,bN+,f(ab)=f(a)f(b)\forall a,b\in\mathbb N^+,f(ab)=f(a)f(b) 的数论函数 ff 我们称为 完全积性函数,不难看出 f(1)=1f(1)=1

满足 a,bN+,ab,f(ab)=f(a)f(b)\forall a,b\in\mathbb N^+,a\perp b,f(ab)=f(a)f(b) 的数论函数 ff 称为 积性函数,同样的,f(1)=1f(1)=1

分析一下可以发现,完全积性函数仅需每个质数处的值即可确定整个函数,考虑唯一分解定理 n=ipicin=\prod_ip_i^{c_i},则 f(n)=if(pi)cif(n)=\prod_if(p_i)^{c_i}

相似的,积性函数的被质数和质数幂处的值决定,f(n)=if(pici)f(n)=\prod_if(p_i^{c_i})

Dirichlet\rm Dirichlet 卷积

定义满足 nN+,h(n)=dnf(d)g(nd)\forall n\in\mathbb N^+,h(n)=\sum_{d|n}f(d)g(\frac n d) 的数论函数 hh 为数论函数 f,gf,gDirichlet\rm Dirichlet 卷积,记作 h=fgh=f*g

为了避免记号混乱,本文使用 fcf^c 表示 ccff 相乘(就是对应位置相乘),fcf^{c*} 表示 ff 做了 ccDirichlet\rm Dirichlet 卷积,例如 f0=ϵ,ff^{0*}=\epsilon,f^{-*}ffDirichlet\rm Dirichlet 逆元。

常见积性函数

最基础也是最重要的,单位元 ϵ\epsilonϵ(n)=[n=1]\epsilon(n)=[n=1],任意函数 fϵ=ff*\epsilon=f

接着我们可以定义 I(n)=1,id(n)=n,idc(n)=ncI(n)=1,id(n)=n,id^c(n)=n^c

然后我们自然好奇 II^{-*},我们定义其为 μ\mu,满足:

n=ipici,μ(n)={0,maxici2(1)ici,maxici1n=\prod_{i}p_i^{c_i},\mu(n)=\begin{cases}0,&\max_ic_i\ge 2\\(-1)^{\sum_ic_i},&\max_ic_i\le 1\end{cases}

μ\mu 作为 II^{-*},在许多位置起到的作用其实是容斥系数,如果每个因数都会把该值对应合法方案统计一次导致统计重复,那么将 fxdxfdf_x\gets\sum_{d|x}f_d 变为 fxdxμ(d)fdf_x\gets \sum_{d|x}\mu(d)f_d 即可统计到真正的答案。

顺便还有 idμid*\mu,我们定义其为 φ\varphi,满足 φ(n)=in[in]\varphi(n)=\sum_{i\le n}[i\perp n]

自然我们就有了如下几个式子:

idμ=φ,Iφ=id,μI=ϵid*\mu=\varphi,I*\varphi=id,\mu*I=\epsilon

记忆法则就是 IIμ\mu 是互为 Dirichlet\rm Dirichlet 逆元的。

还有 σc(n)=in[in]ic,d=σ0\sigma_c(n)=\sum_{i\le n}[i\perp n]i^c,d=\sigma_0 即为约数个数,σ=σ1\sigma=\sigma_1 为约数和。

在估计 d(n)d(n) 的量级时一般取 O(n1/3)\cal O(n^{1/3})

线性筛

线性筛素数/求普通积性函数

普通的埃筛之所以不能做到严格 O(n)\mathcal O(n),还是因为每个数被筛掉了多次,那么我们令每个数在其最小质因子处被筛掉,就做到了严格线性。

1
2
3
4
5
6
7
8
9
10
vec<int> P;bitset<N> is;
void init(int n) {
F(i,2,n) {
if(!is[i]) P+=i;
for(int p:P) if(i*p<=n) {
is[i*p]=1;
if(i%p==0) break;
} else break;
}
}

imodp=0i\bmod p=0,则说明 ii 中最小质因子已经与 pp 相等了,继续枚举 pp 就不是在 i×pi\times p 的最小质因子处被筛掉了,所以需要及时 break

线性筛也可以求普通(常见)积性函数,这里略过,大多利用了其各自的特殊性质。

线性筛 Dirichlet\rm Dirichlet 卷积/任意积性函数

前文说过,积性函数由质数及质数幂处的值决定,所以我们利用这个性质来求解任意可以快速求出“质数及质数幂处的值”的积性函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vec<int> P;int low[N],f[N];
void init(int n) {
f[1]=low[1]=1;
F(i,2,n) {
if(!low[i]) {
P+=i;low[i]=i;
for(ll x=i;x<=n;x*=i) {
//calc f[x]
}
}
for(int p:P) if(i*p<=n) {
is[i*p]=1;
if(i%p==0) {
low[i*p]=low[i]*p;
f[i*p]=f[i/low[i]]*f[p*low[i]];break;
} f[i*p]=f[i]*f[p];low[i*p]=p;
} else break;
}
}

只需单独记录 lowi\text{low}_i 表示 ii 的最小质因子幂即可。

线性筛两个函数的 Dirichlet\rm Dirichlet 卷积也是同理,因为我们可以 O(k)\mathcal O(k) 求出 f(pk)f(p^k) 的值,一个质数的 O(logV)\mathcal O(\log V) 个幂做一个等差数列求和虽然是 O(log2V)\mathcal O(\log^2 V) 的,但由于质数的 log\log 底数较大,实际分析中通常可以分析到常数的级别,此处不展开论述,讲解洲阁筛时仍会涉及到类似的分析。

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
总字数 231.7k 访客数 访问量