首先对一个数操作两次等于没有操作,所以每个数要么操作要么不操作。
首先1和所有质数显然一定要操作。
对于x=p1p2,之前已经被翻转过3次,所以一定要操作。
对于x=p1p2p3,之前已经被翻转过7次,所以一定要操作。
…
对于x=p1p2…pk,之前已经被翻转过2k−1次,所以一定要操作。
这样操作之后所有x=pα11pα22…pαkk都被翻转了2k次,满足要求。
答案就是n∑i=1μ2(i)。
n∑i=1μ2(i)=⌊√n⌋∑i=1μ(i)⌊ni2⌋
杜教筛+整除分块即可。
时间复杂度不会算,反正过了。
#include <iostream>
#include <unordered_map>
#include <cmath>
using namespace std;
const int N = 20000010;
using i64 = long long;
int primes[N], cnt;
bool st[N];
int mu[N];
unordered_map<int, int> ans_mu;
void init(int n) {
mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!st[i]) {
primes[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; j < cnt && primes[j] * i <= n; j++) {
int x = primes[j];
st[i * x] = true;
if (i % x == 0) {
break;
} else {
mu[i * x] = -mu[i];
}
}
}
for (int i = 1; i <= n; i++) mu[i] += mu[i - 1];
}
int sum_mu(int n) {
if (n <= 20000000) return mu[n];
if (ans_mu.count(n)) return ans_mu[n];
i64 res = 1;
for (i64 l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * sum_mu(n / l);
}
return ans_mu[n] = res;
}
int main() {
init(20000000);
i64 n;
cin >> n;
i64 res = 0;
for (i64 l = 1, r; l <= n / l; l = r + 1) {
r = sqrt(n / (n / l / l));
res += (sum_mu(r) - sum_mu(l - 1)) * (n / (l * l));
}
cout << res << '\n';
return 0;
}
膜佬~
请问是怎么把莫比乌斯函数平方求和变成另外一个式子的?需要用到什么数学知识吗?
orz
orz