#include using namespace std; typedef long long LL; const int N = 1e5 + 10; int n = 20; // 筛法求莫比乌斯函数(枚举约数) 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]; } // 最简筛法求莫比乌斯函数(枚举倍数) void get_mobius1(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]; } // 单个数的莫比乌斯函数 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 } int main() { // 计算单个数字的莫比乌斯函数 for (int i = 1; i <= n; i++) printf("%2d ", getmob(i)); cout << endl; for (int i = 1; i <= n; i++) printf("%2d ", i); // 筛法求莫比乌斯函数 // get_mobius1(n); // for (int i = 1; i <= n; i++) // cout << "mu1[" << i << "]=" << mu[i] << endl; // //清空一下,继续测试 // memset(mu, 0, sizeof mu); // //测试枚举约数的筛法 // get_mobius2(n); // for (int i = 1; i <= n; i++) { // //计算单个数字的莫比乌斯函数 // cout << "mu2[" << i << "]=" << getmob(i) << endl; // cout << "mu2[" << i << "]=" << mu[i] << endl; // cout << "========================================" << endl; // } return 0; }