前言
在阅读本文前假设你已经掌握了线性筛,数论分块,常用数论函数和狄利克雷卷积。
题目描述
给定一个正整数 n n n,求 ∑ i = 1 n φ ( i ) \sum_{i=1}^{n}\varphi(i) ∑i=1nφ(i) 和 ∑ i = 1 n μ ( i ) \sum_{i=1}^{n}\mu(i) ∑i=1nμ(i),其中 1 ≤ n ≤ 1 0 9 1\le n\le 10^9 1≤n≤109。
推导过程
设 S ( n ) = ∑ i = 1 n f ( i ) S(n)=\sum_{i=1}^{n}f(i) S(n)=∑i=1nf(i)。
对于任意一个数论函数 g ( n ) g(n) g(n),满足: ∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) \sum_{i=1}^{n}(f*g)(i)=\sum_{i=1}^{n}g(i)S(\left\lfloor \frac{n}{i} \right\rfloor) ∑i=1n(f∗g)(i)=∑i=1ng(i)S(⌊in⌋)。
证明:
∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ x y = i f ( x ) g ( y ) = ∑ x y ≤ n f ( x ) g ( y ) = ∑ y = 1 n ∑ x = 1 ⌊ n y ⌋ f ( x ) g ( y ) = ∑ y = 1 n g ( y ) ∑ x = 1 ⌊ n y ⌋ f ( x ) = ∑ y = 1 n g ( y ) S ( ⌊ n y ⌋ ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) \begin{aligned} \sum_{i=1}^{n}(f*g)(i) &= \sum_{i=1}^{n}\sum_{xy=i}f(x)g(y) \\ &= \sum_{xy\le n}f(x)g(y) \\ &= \sum_{y=1}^{n}\sum_{x=1}^{\left\lfloor \frac{n}{y} \right\rfloor}f(x)g(y) \\ &= \sum_{y=1}^{n}g(y)\sum_{x=1}^{\left\lfloor \frac{n}{y} \right\rfloor}f(x) \\ &= \sum_{y=1}^{n}g(y)S(\left\lfloor \frac{n}{y} \right\rfloor) \\ &= \sum_{i=1}^{n}g(i)S(\left\lfloor \frac{n}{i} \right\rfloor) \end{aligned} i=1∑n(f∗g)(i)=i=1∑nxy=i∑f(x)g(y)=xy≤n∑f(x)g(y)=y=1∑nx=1∑⌊yn⌋f(x)g(y)=y=1∑ng(y)x=1∑⌊yn⌋f(x)=y=1∑ng(y)S(⌊yn⌋)=i=1∑ng(i)S(⌊in⌋)
利用上式构造 S ( n ) S(n) S(n) 关于 ∑ i = 2 n S ( ⌊ n i ⌋ ) \sum_{i=2}^{n}S(\left\lfloor\frac{n}{i}\right\rfloor) ∑i=2nS(⌊in⌋) 的递推式。
∑ i = 1 n ( f ∗ g ) ( i ) = g ( 1 ) S ( n ) + ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) \sum_{i=1}^{n}(f*g)(i)=g(1)S(n)+\sum_{i=2}^{n}g(i)S(\left\lfloor\frac{n}{i}\right\rfloor) i=1∑n(f∗g)(i)=g(1)S(n)+i=2∑ng(i)S(⌊in⌋)
g ( 1 ) S ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) g(1)S(n)=\sum_{i=1}^{n}(f*g)(i)-\sum_{i=2}^{n}g(i)S(\left\lfloor\frac{n}{i}\right\rfloor) g(1)S(n)=i=1∑n(f∗g)(i)−i=2∑ng(i)S(⌊in⌋)
若 f ( n ) f(n) f(n) 是 φ ( n ) \varphi(n) φ(n),我们有 ( φ ∗ 1 ) ( n ) = id ( n ) (\varphi*1)(n)=\text{id}(n) (φ∗1)(n)=id(n),可以令 g ( n ) g(n) g(n) 为 1 ( n ) 1(n) 1(n),所以 ( f ∗ g ) ( n ) = ( φ ∗ 1 ) ( n ) = id ( n ) (f*g)(n)=(\varphi*1)(n)=\text{id}(n) (f∗g)(n)=(φ∗1)(n)=id(n)。
1 ( n ) S ( n ) = ∑ i = 1 n id ( i ) − ∑ i = 2 n 1 ( i ) S ( ⌊ n i ⌋ ) 1(n)S(n)=\sum_{i=1}^{n}\text{id}(i)-\sum_{i=2}^{n}1(i)S(\left\lfloor\frac{n}{i}\right\rfloor) 1(n)S(n)=i=1∑nid(i)−i=2∑n1(i)S(⌊in⌋)
S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n)=\frac{n(n+1)}{2}-\sum_{i=2}^{n}S(\left\lfloor\frac{n}{i}\right\rfloor) S(n)=2n(n+1)−i=2∑nS(⌊in⌋)
这里要预处理出 n 2 3 n^\frac{2}{3} n32 以内的 S ( n ) S(n) S(n),然后使用记忆化搜索和数论分块求解,时间复杂度是 O ( n 2 3 ) O(n^\frac{2}{3}) O(n32)。
若 f ( n ) f(n) f(n) 是 μ ( n ) \mu(n) μ(n),我们同样有 ( μ ∗ 1 ) ( n ) = ε ( n ) (\mu*1)(n)=\varepsilon(n) (μ∗1)(n)=ε(n),可以令 g ( n ) g(n) g(n) 为 1 ( n ) 1(n) 1(n),所以 ( f ∗ g ) ( n ) = ( μ ∗ 1 ) ( n ) = ε ( n ) (f*g)(n)=(\mu*1)(n)=\varepsilon(n) (f∗g)(n)=(μ∗1)(n)=ε(n)。
1 ( n ) S ( n ) = ∑ i = 1 n ε ( i ) − ∑ i = 2 n 1 ( i ) S ( ⌊ n i ⌋ ) 1(n)S(n)=\sum_{i=1}^{n}\varepsilon(i)-\sum_{i=2}^{n}1(i)S(\left\lfloor\frac{n}{i}\right\rfloor) 1(n)S(n)=i=1∑nε(i)−i=2∑n1(i)S(⌊in⌋)
S ( n ) = 1 − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n)=1-\sum_{i=2}^{n}S(\left\lfloor\frac{n}{i}\right\rfloor) S(n)=1−i=2∑nS(⌊in⌋)
接下来跟上面的一样。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define uint unsigned int
#define pii pair<int, int>
template <typename T> using vector2 = vector<vector<T>>;
template <typename T> using MaxHeap = priority_queue<T>;
template <typename T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
#define all(x) (x).begin(), (x).end()
#define endl '\n'
// #define endl " line in : " << __LINE__ << endl
const int N = 2e6 + 5, INF = 1e16, P = 998244353;
unordered_map<int, int> mp_phi, mp_mu;
int phi[N], mu[N];
vector<int> prm;
int vis[N];
int sol1(int n) {
if (n < N) return phi[n];
if (mp_phi.count(n))
return mp_phi[n];
int x = 0;
for (int l = 2; l <= n; ) {
int r = n / (n / l);
x += sol1(n / l) * (r - l + 1);
l = r + 1;
}
return mp_phi[n] = n * (n + 1) / 2 - x;
}
int sol2(int n) {
if (n < N) return mu[n];
if (mp_mu.count(n))
return mp_mu[n];
int x = 0;
for (int l = 2; l <= n; ) {
int r = n / (n / l);
x += sol2(n / l) * (r - l + 1);
l = r + 1;
}
return mp_mu[n] = 1 - x;
}
void test() {
int n;
cin >> n;
cout << sol1(n) << ' ' << sol2(n) << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
phi[1] = 1;
mu[1] = 1;
for (int i = 2; i < N; i++) {
if (vis[i] == 0) {
prm.push_back(i);
phi[i] = i - 1;
mu[i] = -1;
}
for (int p : prm) {
if (i * p >= N)
break;
vis[i * p] = 1;
if (i % p == 0) {
phi[i * p] = phi[i] * p;
mu[i * p] = 0;
break;
}
phi[i * p] = phi[i] * phi[p];
mu[i * p] = -mu[i];
}
}
for (int i = 2; i < N; i++)
phi[i] += phi[i - 1], mu[i] += mu[i - 1];
int T; cin >> T; while (T--)
test();
return 0;
}
例题
最后,送给大家一只。
文章太短了,下次再送。