## 莫比乌斯函数 https://www.cnblogs.com/letlifestop/p/10262757.html // https://blog.csdn.net/qq_42887171/article/details/95237740 要学习莫比乌斯函数需要学习 到 **积性函数**,深度理解 **欧拉筛** 。 ### 一、积性函数 #### 1. 定义 **积性函数**:若$gcd(a,b)=1$,且满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **积性函数** **完全积性函数**:对于任意正整数$a,b$,都满足$f(a*b)=f(a)*f(b)$,则称$f(x)$为 **完全积性函数** #### 2. 性质 1. 若$f(n),g(n)$均为积性函数,则函数$h(n)=f(n)*g(n)$也是积性函数 2. 若$f(n)$为积性函数,则函数$c*f(n)$($c$是常数)也是积性函数,反之一样 3. **任何积性函数都能应用线性筛**,在$O(n)$时间内求出$1\sim n$项(**莫比乌斯函数要用到**),像素数,欧拉函数等都是 **积性函数**。 ### 二、莫比乌斯函数 #### 1. 用途 我们举例一道经典的应用题,求$1$到$N$中与$a$互质的数的个数:根据容斥原理,设$S_i$为$1$到$N$中和$a$有公因子$i$的数的个数,答案为$N−S_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. 定义 莫比乌斯函数是以$19$世纪的数学家亚当·莫比乌斯的名字命名的。它是数论中的一个重要函数,通常用符号 $μ(n)$ 表示。 **莫比乌斯函数的返回值有三种情况**: * ① 若$n=1,μ(n) =1$ * ② 若$n$存在有大于$1$方数因数(如$4$($2$平方),$9$($3$的平方),$27$($3$的立方),则$μ(n) =0$ * ③ $μ(n)$ 的结果取决于$n$根据 **算数基本定理** 分解的 **质因数个数的奇偶性** 来判断。比如$n=3,5,7$就只有一个质因数所以为$μ(n)=-1$,$n=6,15,21$,$μ(n)$就为$1$。 #### 3. 求单个数字的莫比乌斯函数值 ```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 } ``` #### 4.枚举倍数求莫比乌斯函数(埃氏筛) ```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]; } ``` #### 5.枚举约数求莫比乌斯函数(欧拉筛) **[视频讲解](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]; } ```