杜教筛

模板 link

求:$$\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;
}
posted @ 2026-06-27 16:58  Turkey_VII  阅读(13)  评论(1)    收藏  举报