定义:
举个栗子:
假设有两个函数F(n),f(d),且d∈{x,x∣n}
并有以下关系:F(n)等于所有f(d)之和。
比如:6能被1,2,3,6 整除,所以F(6)=f(1)+f(2)+f(3)+f(6)
用一个公示表示就是:F(n)=∑d∣nf(d)
∣ 符号表示整除,a∣b 表示b被a整除,
也就是b有a这个因数,b=ka (k∈N)。
由此可得到:
F(1)=f(1)
F(2)=f(1)+f(2)
F(3)=f(1)+f(3)
F(4)=f(1)+f(2)+f(4)
F(5)=f(1)+f(5)
F(6)=f(1)+f(2)+f(3)+f(6)
F(7)=f(1)+f(7)
稍微变形得到:
f(1)=F(1)
f(2)=F(2)−f(1)=F(2)−F(1)
f(3)=F(3)−F(1)
f(4)=F(4)−f(2)−f(1)=F(4)−F(2)
f(5)=F(5)−F(1)
f(6)=F(6)−F(3)−F(2)+F(1)
f(7)=F(7)−F(1)
f(8)=F(8)−F(4)
这样如果我们知道各个F(n)的值我们肯定能算出各个f(d)的值,只要打表推就可以了,但仔细观察一下,有没有什么规律呢?
好像每一个f(n)都由它所有的因子d∈{x,x∣n}的F(d)乘上一个0或1或−1的系数再相加得到,我们就把这个系数也看成是d的一个函数μ(d),称作莫比乌斯函数。
那莫比乌斯函数的值我们怎么知道呢?有没有一个通项公式?
我们就从最特殊的f(6)着手:
f(6)=F(6)−F(3)−F(2)+F(1)
我们不妨这样看:
f(6)=1×F(16)+(−1)×F(26)+(−1)×F(36)+1×F(66)
此时好像有点端倪了,我们可以将F()中每个分母看作d,且把1看做特殊情况:μ(1)=1,易看出μ(2)=−1,μ(3)=−1,μ(6)=1.
这时相信不少大佬已看出μ(d)的值与d本身互异质因子个数有关。
2只有一个质因子2,3只有一个质因子3,而6有两个质因子2和3。
假设一正整数d的互异质因子个数为k,则μ(d)=(−1)k。
特殊的μ(1)=1.
那有些μ(d)却等于0怎么解释呢?
比如:f(8)=F(8)−F(4),
根据上文的推测,我们知道,
f(8)=μ(1)×F(18)+μ(2)×F(28)+μ(4)×F(48)+μ(8)×F(88)
再看看上文我们已有的结论,正整数d的互异质因子个数这就要求d必须能为k个互异且互质的数的乘积。但是4=2×2不满足互异,8=2×4不满足互质。
所以我们就猜想除1外不能由几个互质且互异的正整数相乘得到的数d的莫比乌斯函数值为0,例:μ(4)=0,μ(8)=0。
下面总结一下:
- μ(d)函数是莫比乌斯函数,如果d=1,μ(d)=1
- 如果d为互异质数p1,p2…pk的乘积(若d本身是个质数就看是它本身一个的乘积),则μ(d)=(−1)k
- 否则,μ(d)=0
然而,我们现在只是会求莫比乌斯函数值,什么是莫比乌斯反演呢?
其实就是下面两个定理:
- 约数关系
若 :F(n)=∑d∣nf(d)
则: f(n)=∑d∣nμ(d)F(dn)
- 倍数关系
若 :F(n)=∑n∣df(d)
则: f(n)=∑n∣dμ(dn)F(d)
性质:
- 莫比乌斯反演公式 :f(n)=∑d∣nμ(d)F(dn)
- μ(n)是积性函数
- 设f是算术函数,他的和函数F(n)=∑d∣nf(d)是积性函数,那么f也是积性函数。
- 对于大于1的正整数n
∑d∣nμ(d)=0
- 对于任意正整数n
∑d∣ndμ(d)=nφ(n)
φ(n)是欧拉函数.
Code:
找[1,n],[1,m]内互质的数的对数,分块优化
ll solve(ll n,ll m )
{
if (n>m)swap(n,m);
ll ret=0;
for (int i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ret+=(sum[last]-sum[i-1])*(n/i)*(m/i);
}
return ret;
}
莫比乌斯函数 线性筛代码:O(n)
const int N=50000;
bool is_prime[N+500];
int prime[N+50];
int mu[N+50];
ll sum[N+50];
ll tot;
void Moblus()
{
tot = 0;
mu[1] = 1;
for(ll i = 2; i < N; i++)
{
if(!is_prime[i])
{
prime[tot++] = i;
mu[i] = -1;
}
for(ll j = 0; j < tot && i*prime[j] < N; j++)
{
is_prime[i*prime[j]] = 1;
if(i % prime[j])
{
mu[i*prime[j]] = -mu[i];
}
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
nlogn 筛法 (因子倍增法):
void pre()
{
for (int i=1; i<=N; i++)
for (ll j=i ; j<=N; j+=i)
ud[j].x+=i;
}