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.

80 lines
2.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n = 27;
//筛法求莫比乌斯函数(枚举约数)
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() {
//筛法求莫比乌斯函数
get_mobius1(n);
for (int i = 1; i <= n; i++) {
//计算单个数字的莫比乌斯函数
cout << "mu1[" << i << "]=" << getmob(i) << endl;
cout << "mu1[" << i << "]=" << mu[i] << endl;
cout << "========================================" << 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;
}