P4213 [template] Du teach sieve (Sum)
Title Description
Given a positive integer $ N (N \ le2 ^ {31} -1) $
begging
$$ans_1=\sum_{i=1}^n\varphi(i)$$
$$ans_2=\sum_{i=1}^n \mu(i)$$
Input and output formats
Input formats:T + 1 total row number of the first data group behavior T (T <= 10) of 2 ~ T + 1 lines each a non-negative integer N, represents a set of query
Output formats:A total of T lines of two spaces separated by a number of ans1, ans2
Sample input and output
AcFirmament solution to a problem of
Du teach screen template
Du teach screen is used to dry clams it?
It can quadrature function of the prefix and a non-linear time.
Pre-knowledge
Multiplicative function
Multiplicative function: For any integers coprime $ a, b $ there is $ f (ab) = f (a) f (b) $ called $ f (x) $ arithmetical functions.
Completely multiplicative function: for any integer $ a, b $ there is $ f (ab) = f (a) f (b) $ arithmetical functions.
- Common multiplicative function: $ \ varphi, \ mu, \ sigma, d $
- Common totally multiplicative function: $ \ epsilon, I, id $
Here special explain the $ \ epsilon, I, id $, respectively, what is the meaning: $ \ epsilon (n) = [n = 1], I (n) = 1, id (n) = n $
Dirichlet convolution
Set $ f, g $ are two arithmetic functions, Dirichlet thereof Convolution is: $ (f * g) (n) = \ sum \ limits _ {d | n} f (d) g (\ frac {n} {d}) $
Properties: commutative, associative
Identity element: $ \ epsilon $ (ie $ f * \ epsilon = f $)
Some properties of Dirichlet convolution binding obtained:
- $ \ Mu * I = \ epsilon $
- $\varphi * I = id$
- $\mu * id = \varphi$
Mobius inversion
若 $$g(n) = \sum\limits_{d|n}f(d)$$
则 $$f(n)=\sum\limits_{d|n}\mu(d)g(\frac{n}{d})$$
Proof: Here we need to use nature previously mentioned: $ \ mu * I = \ epsilon $
Given conditions equivalent to $ g = f * I $
So $ g * \ mu = f * I * \ mu = f * \ epsilon = f $ ie $ g * \ mu = f $ that is the conclusion.
Du teach sieve
Provided multiplicative function now required prefix and $ f $, provided $ \ sum \ limits_ {i = 1} ^ {n} f (i) = S (n) $.
Find a multiplicative function $ g $, consider a prefix thereof Dirichlet convolution and
$$\sum\limits_{i=1}^{n}(f*g)(i)$$
$$\begin{aligned} &= \sum\limits_{i=1}^{n} \sum \limits _{d|i} f(d)g(\frac{i}{d}) \\ &= \sum \limits _{d=1}^{n} g(d)\sum\limits _{i=1}^{\lfloor \frac{n}{d}\rfloor } f(i) \\ &= \sum \limits _{d=1}^{n} g(d) S(\lfloor \frac{n}{d} \rfloor) \end{aligned}$$
Wherein the first line is obtained according to the definition of Dirichlet convolution.
The second line is to get the proposed $ g $ enumerate $ d $.
The third line is obtained $ \ sum \ limits _ {i = 1} ^ {\ lfloor \ frac {n} {d} \ rfloor} f (i) $ replaced $ S (\ lfloor \ frac {n} {d} \ rfloor) $
Next consider $ g (1) S (n) $ equal to what.
Can be found, he is equal to $$ \ sum \ limits _ {i = 1} ^ {n} g (i) S (\ lfloor \ frac {n} {i} \ rfloor) - \ sum \ limits _ {i = 2} ^ {n} g (i) S (\ lfloor \ frac {n} {i} \ rfloor) $$
(As will be understood from the beginning of the prefix and prefix and is subtracted from the first item beginning 2)
The preceding equation $ \ sum \ limits _ {i = 1} ^ {n} g (i) S (\ lfloor \ frac {n} {i} \ rfloor) $, according to the just derived, he is equal to $ \ sum \ limits_ {i = 1} ^ {n} (f * g) (i) $
So get to teach core equation Du screen:
$$g(1)S(n)=\sum\limits_{i=1}^{n}(f*g)(i) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor)$$
After what use is it to get this formula?
Now if can find a suitable multiplicative function $ G $, making it possible to quickly calculated $ \ sum \ limits_ {i = 1} ^ {n} prefix (f * g) (i) $ and $ G $ and, then It can be solved recursively by block number theory.
Code to be understood that this can probably be written (default ll
is long long
) (may be understood as a frame is a pseudo-code idea ..)
ll GetSum(int n) { // 算 f 前缀和的函数
ll ans = f_g_sum(n); // 算 f * g 的前缀和
// 以下这个 for 循环是数论分块
for(ll l = 2, r; l <= n; l = r + 1) { // 注意从 2 开始
r = (n / (n / l));
ans -= (g_sum(r) - g_sum(l - 1)) * GetSum(n / l);
// g_sum 是 g 的前缀和
// 递归 GetSum 求解
} return ans;
}
This code is the complexity of $ O (n ^ {\ frac {3} {4}}) $, proven as follows:
Determined set $ S (n) $ complexity is $ T (n) $, requires a $ S (n) $ necessary to calculate $ \ sqrt n $ a $ S (\ lfloor \ frac {n} {i} \ rfloor) $ value, in conjunction with number theory complexity $ O chunked (\ sqrt n) $ can be obtained: $$ T (n) = \ sum \ limits_ {i = 1} ^ {\ sqrt n} O (\ sqrt i) + O (\ sqrt {\ frac {n} {i}}) = O (n ^ {\ frac {3} {4}}) $$
It can be further optimized Du teach sieve, which is to screen out front linear $ m $ answer, then after Du teach sieve. This complexity is after optimization:
$$T(n) = \sum\limits_{i=1}^{\lfloor \frac{n}{m} \rfloor} \sqrt \frac{n}{i} = O({\frac{n}{\sqrt m}})$$
When $ m = n ^ {\ frac {2} {3}} $ time, $ T (n) = O (n ^ {\ frac {2} {3}}) $
You can use a hash table to save enough has been seeking answers, you can not.
Taking into account the above summation is occurred $ \ lfloor \ frac {n} {i} \ rfloor $. Open a size twice as $ \ sqrt n $ $ dp $ records array of answers. If you need to find now GetSum(x)
, if $ x \ leq \ sqrt n $ , return dp[x]
, otherwise dp[sqrt n + n / i]
you can. This will eliminate the complexity of the hash table.
Practical exercise
Once again hang core (Tao) Heart (LU) type, which all rely on: $$ g (1) S (n) = \ sum \ limits_ {i = 1} ^ {n} (f * g) (i) - \ sum \ limits _ {i = 2} ^ {n} g (i) S (\ lfloor \ frac {n} {i} \ rfloor) $$
Its key is to find the right $ g $ rapidly so that this thing can be considered.
Theoretical knowledge about so much, then look at a few examples:
(1) $ \ mu $ prefix and
Given the nature of Mobius function $ \ mu * I = \ epsilon $, naturally thought take $ f = \ mu, g = I, f * g = \ epsilon $.
Where prefix prefix and $ I $ and $ \ epsilon $ and are weak to burst. .
So it is easy to solve.
Du teach sieve Code:
inline ll GetSumu(int n) {
if(n <= N) return sumu[n]; // sumu是提前筛好的前缀和
if(Smu[n]) return Smu[n]; // 记忆化
ll ret = 1ll; // 单位元的前缀和就是 1
for(int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l); ret -= (r - l + 1) * GetSumu(n / l);
// (r - l + 1) 就是 I 在 [l, r] 的和
} return Smu[n] = ret; // 记忆化
}
(2) $ \ varphi $ prefix and
Considering the $ \ $ varphi properties of $ \ varphi * I = id $, take $ f = \ varphi, g = I, f * g = id $
I.e., $ f * g $ $ prefix and ID is $ $ \ frac {n * (n + 1)} {2} $
Du teach sieve Code:
inline ll GetSphi(int n) {
if(n <= N) return sump[n]; // 提前筛好的
if(Sphi[n]) return Sphi[n]; // 记忆化
ll ret = 1ll * n * (n + 1) / 2; // f * g = id 的前缀和
for(int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l); ret -= (r - l + 1) * GetSphi(n / l);
// 同上,因为两个的 g 都是 I
} return Sphi[n] = ret; // 记忆化
}
(1) & (2) is to teach Du screen template luogu p4213
(3) (综合)$\sum\limits_{i=1}^{n}\varphi(i) \cdot i$
Order $ f = \ varphi \ cdot id, g = id $, consider the convolution Dealey Cray obtained in the form $ (f * g) (n) = \ sum \ limits _ {d | n} (\ varphi (d) \ cdot d) \ cdot (\ frac {n} {d}) = n \ sum \ limits_ {d | n} \ varphi (d) = n ^ 2 $
即 $(f * g)(i) = i^2$
This can be obtained quickly $ (f * g) (i) $ prefix and $ \ frac {n (n + 1) (2n + 1)} {6} $
On it.
topic
To recommend Los Valley template title
There is also a question luoguP3768 simple math formula can be used to push this question End Du teach sieve to seek $ \ varphi (i) i ^ 2 $ and prefix, and $ \ varphi (i) i $ not much different.
There are many topics to teach Du screen on 51nod, put a few:
- 51nod 1244
- 51nod 1237
- 51nod 1238
- 51nod 1239
- 51nod 1220
- ...
Then the card is always optimized card with the open space, unordered_map fucks.
#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
T data=0,w=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;
co int N=6500000;
int pri[N],tot;
LL mu[N],phi[N];
void sieve(){
pri[1]=mu[1]=phi[1]=1;
for(int i=2;i<N;++i){
if(!pri[i]) pri[++tot]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=tot&&i*pri[j]<N;++j){
pri[i*pri[j]]=1,mu[i*pri[j]]=-mu[i],phi[i*pri[j]]=phi[i]*phi[pri[j]];
if(i%pri[j]==0){
mu[i*pri[j]]=0,phi[i*pri[j]]=phi[i]*pri[j];
break;
}
}
}
for(int i=2;i<N;++i) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
unordered_map<int,LL> smu,sphi;
LL sum_mu(int n){
if(n<N) return mu[n];
if(smu.count(n)) return smu[n];
LL ans=1;
for(unsigned l=2,r;l<=n;l=r+1){ // 2^32-1
r=n/(n/l);
ans-=(r-l+1)*sum_mu(n/l);
}
return smu[n]=ans;
}
LL sum_phi(int n){
if(n<N) return phi[n];
if(sphi.count(n)) return sphi[n];
LL ans=(LL)n*(n+1)/2;
for(unsigned l=2,r;l<=n;l=r+1){
r=n/(n/l);
ans-=(r-l+1)*sum_phi(n/l);
}
return sphi[n]=ans;
}
int main(){
cerr<<(sizeof(pri)+sizeof(phi)+sizeof(mu))/1024.0/1024<<endl;
sieve();
for(int t=read<int>();t--;){
int n=read<int>();
printf("%lld %lld\n",sum_phi(n),sum_mu(n));
}
return 0;
}