本人菜鸡,第一次写莫比乌斯的东西,如果有错误的话,还请各位大大指出,顺便轻喷···
首先介绍莫比乌斯反演:
观察图片里这个函数关系,我们现在有函数F与f

用公式来描述就是

其中d是x的所有因子
现在想一下,怎么用F来把f表示出来
不难得到

写成公式表示就是

那么问题来了,u是什么?答:大名鼎鼎的莫比乌斯函数
也就是求出莫比乌斯函数之后,我们就可以通过这个公式和F函数的值,求出f。主要意义就是这样做可以减少运算量。毕竟有的时候我们要求的f(x)可能很难算,或者复杂度太高。能通过求出来可以轻松得到的F,然后推导f(x)是十分划算的。
那么,我们先来了解一下莫比乌斯函数

求法也十分简单,莫比乌斯函数是积性函数,满足

而我们以前所学的线性欧拉筛,也满足这个,也就是说,我们可以直接用线性欧拉筛来预处理莫比乌斯函数,这个板子也很好找。相对的,所有积性函数,都可以用欧拉筛预处理。
那么,开始正题:反演
莫比乌斯反演一共有两种形式:
1.约数形式:

2.倍数形式:(做题更常用)

到这里为止都不难,莫比乌斯的题目的主要问题是构造,你得知道F设置成什么比较好,因为要快速求出f,就必须要求F能够快速求出。第二个问题才是公式的推导。数学真的容易杀人
在当前题目
n个数,求出其中任意m个数的所有m元公质数,如果我们能够求出在给定的n个数字中,每个数字x有多少数字与其互质,不妨记为res[x],那么,只有我们从res[x]中取出m个数字,x必然是这m个数字的m元公质数,其对答案的贡献就是result+=x;那么考虑对数,首先是x可能有多个然后是取出m个数字,是一个组合数,也就是我们的result可以写成C(res[x],m) * x * cnt[x]的形式,然后枚举每一个x就好。
现在的难点就是怎么求出rex[x],即,对于每一个数字x,有多少个数字与其互质。
转化为数学公式

其中x就是我们要当前枚举的数字,公式计算的过程中是一个常数。我们要求的就是f(1)
和平时不同的是,这里直接求f(1)我不会,我只会板子推法,从概括到一般。我们先求出f(k),然后带入k=1;
重点

我们令F(k)为,a[i]与x的最大公约数是k的倍数的个数,即gcd=k,2k,3k…,我们把这个gcd值设为d

要知道F可以在nlog(n)全部预处理结束
因为F(k)就等于所有数字里,大小是k的整数倍的数字的个数。
我们用桶的方式来记录每一个数字,那么直接for循环,从k到max,k+=k,然后F+=cnt[k]即可,再加上外层枚举k,二层循环,循环次数是max+max/2+max/3+max/4······,化成函数积分后,结果收敛为max*log(max),复杂度可以接受。(F的处理如下图所示)

然后就是一个标准的倍数形式的莫比乌斯反演:
枚举k的整数倍d,上限为能取到的最大值。

k=1带入

F(d)预处理过,可以直接带入
上代码:
#include <iostream>
using namespace std;
typedef long long LL;
const int mod=998244353;
const int N=1e5+10;
int mo[N],f[N],prime[N],num=0,a[N];
int cnt[N

本文介绍了如何利用莫比乌斯反演解决编程问题,特别是西北工业大学‘编程之星’挑战赛中的I题。文章详细讲解了莫比乌斯函数的概念、计算方法和在约数、倍数形式下的反演,同时通过实例展示了如何应用这些理论解决实际的算法挑战,包括计算互质数量和公质数。在讨论过程中,作者分享了自己的学习过程和解题思路。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



