反演
反演的作用基本上就是将一个bool表达式转化成一个和式,从而减小程序的时间复杂度。
欧拉反演
欧拉反演是莫比乌斯反演的一种特例,通常用于解决gcd的求和问题,它的基本式子是
下面简单证明一下,我们枚举(n)的每个因子(d),显然每个因子都有可能成为(n)与(1-n)中的数的gcd,并且每个gcd都是,即(n=sum_{d|n}sum_{i=1}^{n}[gcd(i,n)==d]),其中([gcd(i,n)==d])这个是一个bool表达式,当且仅当([gcd(i,n)==d])时,该式子返回1,其余时候返回0。
进一步化简得到
因为在枚举约数的时候,对于一个约数(d),总会有一个约数(frac{n}d)与之对应(可能相等),即所有的约数都是对称的,所以原式可以继续化简为
证毕。
有什么用呢?
来看一个十分眼熟的式子。
求(sum_{i=1}^ngcd(i,n))的值。
相信一些大佬会秒算出答案,即(sum_{d|n}d imesphi(frac{n}d))
不如换一个角度推导,根据上述中的(n=sum_{d|n}phi(d))来化简一下。
显然每个(d)对答案的贡献只有(frac{n}d)个,好吧并不显然,举个例子,假设(d=1),那么(d)能整除这全部(n)个数,答案就会增加(n imesphi(1)),类似的,对于每个(d),答案都会增加(frac{n}d imesphi(d)),所以上式化简为
因为约数是对称的,所以它和上边那个一眼的式子是相等的。
虽然到这里反演仍旧没有发挥什么很大的作用,但是我们不妨继续魔改上边的式子,这次——
求(sum_{i=1}^nsum_{j=1}^ngcd(i,j))的值。这个总不能一眼看出答案吧
所以我们继续反演
直到这一步和上边的推导还是相似的,我不会告诉你我是复制的
但是我们发现它不能像上边的式子继续化简了,因为(i,j)都是不确定的量,如果直接枚举,时间复杂度没有任何变化,仍旧是(O(N^2)),思考一下(i,j)共同有的是什么,没错是(d)。
于是可以枚举(d)
对于每个约数(d),它所能造成的贡献还是(frac{n}d),不过由于这次没有条件(d|n),所以需要稍微变化一点,手模一下发现它成了(lfloorfrac{n}d floor),但在代码上边还是(n/d),上式继续化简为
但是代码里要写成这样
(n/d)*(n/d)*phi[d];
而不是
n/d*n/d*phi[d];
因为必须要先向下取整再进行运算。
也许这样还有别的奇奇怪怪的方法可以算出来,于是继续改变上述式子。
求(sum_{i=1}^nsum_{j=1}^mgcd(i,j))的值
这个莫比乌斯反演也可以做,不过好像没有必要,仍旧套上边欧拉反演的式子,得到原式为
以上就是欧拉反演了,虽然有些时候用起来还可以但是大多时候有局限性,所以建议学习莫比乌斯反演
莫比乌斯反演
好了,那如果问题继续发展,改成——
求(sum_{i=1}^nsum_{j=1}^ngcd(i,j)==k)的值呢?
但这样好像就没有办法使用欧拉反演了,于是我们考虑使用其它办法。
首先引入一个函数(mu),它的定义为
其实这就是所谓的莫比乌斯函数,深刻理解一下它的含义,特殊的,当(x==1)的时候,它的值为1,否则当(x)中所含的单个质因子数目不超过1时,它的值为-1的质因子数目次方,其余情况为0。
假设在有两个定义在复数域上的函数(f,g)满足
那么有
至于证明,个人感觉使用Dirichlet卷积会比较好证明一点。
定义两个数论函数(f,g)的Dirichlet卷积为
((f*g)(n)=sum_{d|n}f(d)g(frac{n}d))
然后再介绍一些基本的数论函数
(varepsilon(x))当且仅当(x==1)时返回1
(d(x))返回(x)的约数个数
(sigma(x))返回(x)的约数和
(varphi(x))这个返回啥感觉可以不说
(id(x))返回(x)
(I(x))返回1
由卷积的定义可知,原问题可以化为
已知
求证
这里我们用一个很常用的性质,
即
我们先来证明一下,
也就是相当于求(n)的因子的莫比乌斯函数值的和。
因为只有在一个数的单个质因子不超过1时,才会返回不为0的值,所以只需要考虑(d)中的质因子。
假设(d)中共含有(k)个质因子,那么原式可以化为
于是你就会发现一个很神奇的东西,这个就是…二项式定理。
所以
当且仅当(k==0)时,原式为1,易得此时(n==1)。
证毕
所以,对
两边同时卷上(mu),得到
然后
Dirichlet 卷积满足交换律和结合律。
证明 百度百科说的
即
Dirichlet 卷积还有很多性质,比如
由这个可以得到什么呢?
两边同时卷上(I),会得到
即
把它卷出来就会发现,这不就是欧拉反演的式子吗!
那我们回到正题,求(sum_{i=1}^nsum_{j=1}^ngcd(i,j)==k)
设
那么反演一下,得到
令(T=frac{k}d)
这么推导十分满足莫比乌斯反演的式子,但好像两个函数比较难设出来,所以可以采取一个强大某些时候可能推不出来的办法。
举个例子
上边我们已经证明了
用(gcd)替换(n)得到
换一下位置
仍旧像欧拉反演那样,枚举每一个(d),分别计算贡献。
推出来的式子是一样的。
但是这样的时间复杂度可能还是(O(n))的,在面临很多询问的时候仍旧会挂,于是考虑继续优化,这时候需要用到整除分块,有一部分数,他们(lfloorfrac{n}{kd} floor)的值是一样的,并且对于值为(lfloorfrac{n}{i} floor)的块,它的右端点为(lfloorfrac{n}{lfloorfrac{n}{i} floor} floor),我们可以先线性筛出(mu)的前缀和,然后对于这些值一样的数一起计算,这样时间复杂度就是(O(sqrt n))的了。