这个算法,,最早于今年三月初从刘巨佬处听闻,今天才算初步学习了一下。
这是一个非常神奇的算法,它可以将一些不好求的东西转化为一些好求的东西。然后一般来说会套用整除分块。所以不了解整除分块的同学可以看我下一篇博客,,待会儿马上写。
我们现在正式开始。
首先来看看莫比乌斯函数,我们叫它mu~
莫比乌斯函数
这个函数的定义是
对于(i),当i=1时,该函数为1。
当i可以被分解为k个质因数相乘,并且这k个质因数互相不相同(也就是没有大于1次的项),则该函数为。
反之,当有多次项的时候,函数为0。
这个函数的定义好长啊。
我们现在引入一个我懒得证明的定理。
1.
意思是说,当n=1时,函数为1,反之为0.
用人话说当n!=1时,所有n的约数的莫比乌斯函数和为0。
听说这个定理可以用什么容斥系数证明,,不晓得什么东西。
并且莫比乌斯函数的一个很棒棒的地方在于,它的筛法和素数几乎一样ovo。
上代码
void mumumumu(int n)
{
mu[1]=1;//记录莫比乌斯函数值 ,第一个是1
for(int i=2;i<=n;i++)//筛吧筛吧
{
if(!vis[i]){prim[++cnt]=i;mu[i]=-1;}//一旦这个没有查过,说明是质数,质数分解质因数只有自己一个,所以为-1.
for(int j=1;j<=cnt&&prim[j]*i<=n;j++)//往后筛
{
vis[prim[j]*i]=1;//更新标记
if(i%prim[j]==0)break;//经典的i%pj==0
else mu[i*prim[j]]=-mu[i];
//如果当前mu为-1,则下一个mu的质因数有两个,为1.
//如果当前mu为0,说明质因数已经出现多次项,那下一个也为0.
//如果当前mu为1,说明质因数有偶数个不同的,
//并且当前i%pj==0的情况已经被break,所以下一个加上就是奇数个相异质数,为-1.
}
}
}
这个代码的最后一步十分巧妙,详情已经写上去了。
介绍完了莫比乌斯函数,我们引入莫比乌斯反演。
莫比乌斯反演
一个没有普适性的算法是活不长久的,我们来看看这个东西。
定义为非负整数集合上的两个函数。并且有
则满足
这,就是莫比乌斯反演。它适用于一切符合定义的这样的函数。一般来说,F都要比f好求。
推荐各位选做下列例题
YY的gcd
problem b
约数个数和
zap-queries