莫比乌斯与欧拉函数及反演 / 杜教筛从入门到入土
\(\texttt{2019.10.11}\) 月考结束后开始填坑。学莫比乌斯反演需要深厚的小学数学基础 , 或许你还要知道什么是函数。
莫比乌斯反演没有用的 , 有函数性质就可以了。\(\text{Luogu}\) 博客 里有例题。
符号定义
符号 :
-
艾佛森括号 :
\([a] = \begin{cases} 1 & (a\ \text{is True}) \\ 0 & (a\ \text{is False}) \\ \end{cases}\) -
\(k\{\}\) 代表整个序列每个数字。\(k_i\) 代表其中 \(k\{\}\) 其中一个数字。
-
\(x \perp y\) 代表 \(x\) 与 \(y\) 互质。
函数 :
- \(\text N(n)=n\)
- \(\text I(n)=1\)
- \(\epsilon(n)=[n=1]\)
- 我们设 \(\text{Sum}(h,n)\) 为 \(\sum\limits^{n}_{i=1} h(i)\)
积性函数
这种函数是一类函数的统称 , 假如 \(f\) 是此类函数且满足 (\(x \perp y\)) , 满足性质 :
其中完全积性函数可以满足 \(x \not \perp y\) 的情况。
狄利克雷卷积
如果有积性函数 \(f,g\) , 那么它们的卷积就是 : (\(d\) 是 \(n\) 的因数 , 且 \(*\) 为卷积而不是乘号)
满足封闭性 , 卷来卷去它还是积性函数 , 证明 : \((x \perp y)\)
因为 \(x \perp y\) , 所以它们没有共同因数 , \(a \perp b\)。
它满足交换律 (\(d\) 和 \(\frac{n}{d}\) 出现相同) , 结合律证明 :
它还满足分配率 , 证明 :
这个东西到后面会有用。
莫比乌斯函数
我们知道一个正整数 \(n\) 可以被分解为 : (分解质因数)
那么其莫比乌斯函数就是 :
\(\mu\) 是一个积性函数 , 证明 :
所以它们都是 \((-1)^{t_x+t_y}\)。
\(\mu\) 有一个非常常用的性质 :
也就是所谓的 :
证明一 : (你或许要知道一些组合数知识)
我们不妨把那个东西写成 :
我们考虑只有这样子的数才可以有正或负的贡献 :
那如果所到达的 \(t\) 是奇数 , 负数贡献 \(-1\)。如果是偶数 , 正数贡献 \(1\)。那么我们有很多在 \(n\) 中选取奇数或者偶数个素数组合成 \(n\) 的一个因数的做法 , 那么这个东西可以用 \(C^n_m\) 来表示。
我们考虑一个 \(n\) 的 \(t_n\) , 那么它的贡献应该是 :
我们知道 \(C^n_m=C^n_{n-m}\) 。考虑一个 \(m\) 对应一个 \(n-m\) 。 考虑 \(n\) 是奇数 , \(m\) 是奇数 , 那么 \(n-m\) 肯定是一个偶数。如果 \(m\) 是偶数 , 那么 \(n-m\) 是一个奇数。
那么 \(n\) 不是奇数的时候 , \(C^n_m=C^{n-1}_m+C^{n-1}_{m-1}\) , 后面两个都是奇数为 \(0\) , 那么 \(n\) 为偶数的时候也是 \(0\)。得证。
证明二:
对于 \(n=1\),原式显然成立。
由于狄利克雷卷积的封闭性 , 可知 \(\mu*\text I\) 也是积性函数。
故对于 \(n > 1\),考虑将其分解质因数,于是只需考虑素数次幂的点值。
对于素数 \(p\) , \((\mu*\text I)(p^k) = \sum\limits_{i=0}^k \mu(p^i) = \mu(1) + \mu(p) = 0\)。故原式成立。
来自巨佬 \(\text{alpha1022}\)。
有这个函数一般的题目都可以做 , 比莫比乌斯反演有用。
例题
见 \(\texttt{Luogu}\) 博客。
莫比乌斯反演
假如有 \(f,g\) 两个积性函数 , 且满足 :
则有 :
证明 :
简化一下就变成这样 :
至于结合律的转化可以看上面证明。这个东西比较适合于证明。
欧拉函数
定义就很简单 , 逆元方面走这里 : \(\text{Link}\) 。
欧拉反演
欧拉反演及 :
也就是所谓 :
证明 :
为什么 \(\sum\limits_{d|n} \sum\limits^{n}_{i=1} [\gcd(i,n)=d]\) 等于 \(n\) ?
假如你给 \(1 ... n\) 里面的数的贡献按照它与 \(n\) 的 \(\gcd\) 分类 , 那么它们的贡献总和一定是 \(n\)。而既然是 \(n\) 的 \(\gcd\) , 那么结果一定是 \(n\) 的因数。得证。
\(\phi\) 与 \(\mu\) 的关系
这个东西很简单 :
杜教筛
这个东西很神奇 , 可以在 \(O(n^{\frac{2}{3}})\) 的时间求 \(\sum\limits^n_{i=1} f(i)\) , 其中 \(f\) 为积性函数。
我们有一个 \(g\) 函数 , 如果是积性 , 那么我们有一个 \((f*g)(n)=h(n)\)。则有 :
此谓杜教筛的常用套路。假如我们可以在 \(O(1)\) 的时间内求出 \(\text{Sum}(h,n)\) , 并且 \(f\) 状态可定 ( 通常为 \(\text I\) 之类的 ), 就可以在不断递归最后面的 \(\text {Sum}(g,\lfloor\frac{n}{d}\rfloor)\) , 达到接近于 \(n^{\frac{2}{3}}\) 的复杂度。
复杂度证明 : \(\text{Ark}\) 。
求 : \(\sum \mu\)
如果 \(\text I(x)=1\),那我们知道 \((\mu * \text I)(n)=[n=1]\)。我们就把 \(g\) 代为 \(\text I\),把 \(h\) 代为 \([n=1]\)。
求 : \(\sum \phi\)
已知 \((\phi*\text I)(n)=n\)。
\(\texttt{Code}\)
实现方法 : 预处理到一个比较大的数字 , 我是暴力 \(O(n \log n)\) 筛函数 , 所以调到 \(10^6\) 比较合适。其次我们每筛完一个值的答案就用链式前向星把它连起来 , 模拟无错哈希 , 分三个指针 \(from,reach,value\) 分别代表哈希后的值 , 原来的值 , 这个值所对的函数的前缀和答案。查找的时候就可以全部扫一遍看一看有没有求过。实测 \(tot \leq 10^4\) , 一个数字连最多会冲突 \(15\) 个 , 小常数。
Uses math;
Const
total=100000;
prepare=1000000;
hash_num=5000000;
var
next,reach:array[-1..total] of longint;
phi,mobius:array[-1..prepare] of longint;
cnt:array[-1..hash_num] of longint;
incea:array[-1..prepare] of int64;
ans:array[-1..10,1..2] of qword;
value:array[-1..total] of int64;
i,j,tot,test,maxn:longint;
procedure Link(l,r:longint;sum:int64);
begin
inc(tot); reach[tot]:=r; value[tot]:=sum;
next[tot]:=cnt[l]; cnt[l]:=tot;
end;
function Sieve_phi(n:longint):qword;
var i,j,k:longint;
begin
if n<=prepare then exit(incea[n]); k:=0;
Sieve_phi:=0; j:=0; i:=cnt[n mod hash_num];
while i<>-1 do begin inc(k); maxn:=max(maxn,k); if reach[i]=n then exit(value[i]); i:=next[i]; end; i:=2;
repeat
j:=n div (n div i);
inc(Sieve_phi,Sieve_phi(n div i)*(j-i+1)); i:=j+1;
until i>n;
Sieve_phi:=n*(n+1) >> 1-Sieve_phi; Link(n mod hash_num,n,Sieve_phi);
end;
function Sieve_mobius(n:longint):int64;
var i,j,k:longint;
begin
if n<=prepare then exit(incea[n]); k:=0;
Sieve_mobius:=0; j:=0; i:=cnt[n mod hash_num];
while i<>-1 do begin inc(k); maxn:=max(maxn,k); if reach[i]=n then exit(value[i]); i:=next[i]; end; i:=2;
repeat
j:=n div (n div i);
inc(Sieve_mobius,Sieve_mobius(n div i)*(j-i+1)); i:=j+1;
until i>n;
Sieve_mobius:=1-Sieve_mobius; Link(n mod hash_num,n,Sieve_mobius);
end;
begin
filldword(cnt,sizeof(cnt) >> 2,maxlongint << 1+1);
read(test); mobius[1]:=1; phi[1]:=1; for i:=1 to test do read(ans[i,1]);
for i:=1 to prepare do phi[i]:=i;
for i:=1 to prepare do for j:=2 to trunc(prepare/i) do dec(phi[i*j],phi[i]);
for i:=1 to prepare do incea[i]:=incea[i-1]+phi[i];
for i:=1 to test do ans[i,2]:=Sieve_phi(ans[i,1]);
filldword(cnt,sizeof(cnt) >> 2,maxlongint << 1+1);
fillchar(value,sizeof(value),0); fillchar(reach,sizeof(reach),0);
fillchar(incea,sizeof(incea),0); fillchar(next,sizeof(next),0);
for i:=1 to prepare do for j:=2 to trunc(prepare/i) do dec(mobius[i*j],mobius[i]);
for i:=1 to prepare do incea[i]:=incea[i-1]+mobius[i];
for i:=1 to test do begin writeln(ans[i,2],' ',Sieve_mobius(ans[i,1])); end;
end.
鸣谢 :
\(\text{DimensionTripper}\)、\(\text{peng-ym}\) 、\(\text{alpha1022}\) 大佬