杜教筛
求:$$\large \sum^{n}_{i=1} \mu(i)$$
其中 \(n \le 2^{31}\)。
设答案为 \(S(n)\)。
由于 \(\mu * \zeta = \epsilon\),所以 $$\large \sum_{i=1}^{n} \epsilon = \sum_{i=1}^{n} \sum_{d|n}\mu(d)\zeta(\frac{i}{d})$$
所以 $$\large \sum_{i=1}^{n} \epsilon = \sum_{d=1}^{n} \sum_{i = 1}^{\lfloor \frac{n}{d} \rfloor}\mu(d)\zeta(i)$$
\[\large \sum_{i=1}^{n} \epsilon = \sum_{d=1}^{n} \zeta(i) \sum_{i = 1}^{\lfloor \frac{n}{d} \rfloor}\mu(d)
\]
\[\large \sum_{i=1}^{n} \epsilon = \sum_{d=1}^{n} \zeta(i) S(\lfloor \frac{n}{d} \rfloor)
\]
\[\large \sum_{i=1}^{n} \epsilon = S(n)\zeta(1)+\sum_{d=2}^{n} \zeta(i) S(\lfloor \frac{n}{d} \rfloor)
\]
\[\large S(n) =\sum_{i=1}^{n} \epsilon-\sum_{d=2}^{n} \zeta(i) S(\lfloor \frac{n}{d} \rfloor)
\]
递归计算,复杂度不会证。\(\phi\) 同理化简。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7 + 5;
int T, n, tot, phi[N], prime[N], sumphi[N], mu[N], summu[N];
bool vis[N];
unordered_map<int, int> mp1, mp2;
inline void init(){
sumphi[1] = phi[1] = 1;
summu[1] = mu[1] = 1;
for(int i = 2; i < N; i++){
if(!vis[i]) prime[++tot] = i, phi[i] = i - 1, mu[i] = -1;
for(int j = 1; j <= tot && prime[j] * i <= N; j++){
vis[i * prime[j]] = 1;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
mu[i * prime[j]] = 0;
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
}
sumphi[i] = sumphi[i - 1] + phi[i];
summu[i] = summu[i - 1] + mu[i];
}
}
inline int djs1(int n){
if(mp1[n]) return mp1[n];
if(n < N) return sumphi[n];
int ans = 0;
for(int l = 2, r; l <= n; l = r + 1){
r = n / (n / l);
ans += (r - l + 1) * djs1(n / l);
}
return mp1[n] = n * (n + 1) / 2 - ans;
}
inline int djs2(int n){
if(mp2[n]) return mp2[n];
if(n < N) return summu[n];
int ans = 0;
for(int l = 2, r; l <= n; l = r + 1){
r = n / (n / l);
ans += (r - l + 1) * djs2(n / l);
}
return mp2[n] = 1 - ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
init();
cin >> T;
while(T--){
cin >> n;
cout << djs1(n) << " " << djs2(n) << '\n';
}
return 0;
}

浙公网安备 33010602011771号