You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
4.2 KiB

2 years ago
## 莫比乌斯函数
2 years ago
https://blog.csdn.net/qq_49593247/article/details/120394226
2 years ago
2 years ago
https://www.cnblogs.com/letlifestop/p/10262757.html
2 years ago
2 years ago
// https://blog.csdn.net/qq_42887171/article/details/95237740
要学习莫比乌斯函数需要学习 到 **积性函数**,深度理解 **欧拉筛** 。
### 一、积性函数
2 years ago
#### 1. 定义
**积性函数**:若$gcd(a,b)=1$,且满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **积性函数**
**完全积性函数**:对于任意正整数$ab$,都满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **完全积性函数**
#### 2. 性质
2 years ago
1. 若$f(n),g(n)$均为积性函数,则函数$h(n)=f(n)*g(n)$也是积性函数
2. 若$f(n)$为积性函数,则函数$c*f(n)$($c$是常数)也是积性函数,反之一样
2 years ago
2 years ago
3. **任何积性函数都能应用线性筛**,在$O(n)$时间内求出$1\sim n$项(**莫比乌斯函数要用到**),像素数,欧拉函数等都是 **积性函数**。
2 years ago
### 二、莫比乌斯函数
2 years ago
#### 1. 用途
我们举例一道经典的应用题,求$1$到$N$中与$a$互质的数的个数:根据容斥原理,设$S_i$为$1$到$N$中和$a$有公因子$i$的数的个数,答案为$NS_2-S_3-S_5-S_7...+S_{2,3}+S_{3,5}+S_{2,5}...$,可以发现,其答案为$\large \displaystyle \sum_{i=1}^{N}\mu(i)*S_i$。
> **注**:在使用容斥原理解决计数问题时,莫比乌斯函数的值就是每一项的系数,要么是$1$,要么是$-1$。这是因为莫比乌斯函数在容斥原理中的作用就是用来表示每个子集合的权重,从而在计算中起到排除重复计数的作用。
#### 2. 定义
2 years ago
2 years ago
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202312151650942.png)
2 years ago
2 years ago
莫比乌斯函数是个分段函数,它的意思:
- ① 当$n=1$时,莫比乌斯函数值为$1$
- ② 当$n$为可以分解为许多素数并且这些质因子的次数都是$1$时,莫比乌斯值就是$-1$的 **质数因子个数的幂次方**
- ③ 除了这些情况剩余的情况莫比乌斯函数值都是$0$
2 years ago
2 years ago
前五十个数的莫比乌斯值.
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202312151653968.png)
2 years ago
2 years ago
打印前$20$个数字的莫比乌斯函数值
```cpp {.line-numbers}
函数值 1 -1 -1 0 -1 1 -1 0 0 1 -1 0 -1 1 1 0 -1 0 -1 0
数 字: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
```
2 years ago
#### 3. 求单个数字的莫比乌斯函数值
2 years ago
```cpp {.line-numbers}
//单个数的莫比乌斯函数
int getmob(LL x) {
int sum = 0;
for (LL i = 2; i <= x / i; i++) { //从2开始一直到 sqrt(x),枚举所有可能存的小因子
int cnt = 0;
if (x % i == 0) { //如果x可以整除i
while (x % i == 0) cnt++, x /= i; //计数并且不断除掉这个i因子
if (cnt > 1) return 0; //如果某个因子存在两个及以上个则返回0
sum++; //记录因子个数
}
}
if (x != 1) sum++; //如果还存在另一个大因子,那么因子个数+1
return (sum & 1) ? -1 : 1; //奇数个因子,返回-1,否则返回1
}
```
2 years ago
#### 4.枚举倍数求莫比乌斯函数(埃氏筛)
2 years ago
```cpp {.line-numbers}
//枚举倍数求莫比乌斯函数
LL mu[N] , sum[N];
void mobius(LL x) {
mu[1] = 1;
for (LL i = 1; i <= x; i++)
for (LL j = i + i; j <= x; j += i)
mu[j] -= mu[i];
// 维护u(x)前缀和
for (LL i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
}
```
2 years ago
#### 5.枚举约数求莫比乌斯函数(欧拉筛)
2 years ago
**[视频讲解](https://www.bilibili.com/video/BV1Te4y1C7DP)**
```cpp {.line-numbers}
LL mu[N] , sum[N];
int primes[N], cnt;
bool st[N];
void get_mobius2(LL n) {
mu[1] = 1;
for (LL i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
mu[i] = -1;
}
for (LL j = 0; primes[j] <= n / i; j++) {
LL t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0) {
mu[t] = 0;
break;
}
mu[t] = mu[i] * -1;
}
}
// 维护u(x)前缀和
for (LL i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
}
```