The Du sieve is used to compute prefix sums of a class of number-theoretic functions. For a number-theoretic function f f f , it can compute S ( n ) = ∑ i = 1 n f ( i ) S(n)=\sum_{i=1}^{n}f(i) S ( n ) = ∑ i = 1 n f ( i ) in sublinear time.
Algorithmic Idea
We seek to construct a recurrence for S ( n ) S(n) S ( n ) in terms of S ( ⌊ n i ⌋ ) S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) S ( ⌊ i n ⌋ ) .
For any number-theoretic function g g g , we have
∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) \begin{aligned}
\sum_{i=1}^{n}(f * g)(i) & =\sum_{i=1}^{n}\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right) \\
& =\sum_{i=1}^{n}g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned} i = 1 ∑ n ( f ∗ g ) ( i ) = i = 1 ∑ n d ∣ i ∑ g ( d ) f ( d i ) = i = 1 ∑ n g ( i ) S ( ⌊ i n ⌋ )
where f ∗ g f*g f ∗ g is the Dirichlet convolution of the number-theoretic functions f f f and g g g .
Sketch of Proof
The term g ( d ) f ( i d ) g(d)f\left(\frac{i}{d}\right) g ( d ) f ( d i ) contributes to every i ≤ n i\leq n i ≤ n . Therefore, changing the enumeration order and enumerating d d d and i d \frac{i}{d} d i (corresponding to the new i , j i,j i , j ) gives
∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) = ∑ i = 1 n ∑ j = 1 ⌊ n / i ⌋ g ( i ) f ( j ) = ∑ i = 1 n g ( i ) ∑ j = 1 ⌊ n / i ⌋ f ( j ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) \begin{aligned}
\sum_{i=1}^n\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right) & =\sum_{i=1}^n\sum_{j=1}^{\left\lfloor n/i \right\rfloor}g(i)f(j) \\
& =\sum_{i=1}^ng(i)\sum_{j=1}^{\left\lfloor n/i \right\rfloor}f(j) \\
& =\sum_{i=1}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned} i = 1 ∑ n d ∣ i ∑ g ( d ) f ( d i ) = i = 1 ∑ n j = 1 ∑ ⌊ n / i ⌋ g ( i ) f ( j ) = i = 1 ∑ n g ( i ) j = 1 ∑ ⌊ n / i ⌋ f ( j ) = i = 1 ∑ n g ( i ) S ( ⌊ i n ⌋ )
Thus we obtain the recurrence
g ( 1 ) S ( n ) = ∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) \begin{aligned}
g(1)S(n) & = \sum_{i=1}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& = \sum_{i=1}^n (f * g)(i) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned} g ( 1 ) S ( n ) = i = 1 ∑ n g ( i ) S ( ⌊ i n ⌋ ) − i = 2 ∑ n g ( i ) S ( ⌊ i n ⌋ ) = i = 1 ∑ n ( f ∗ g ) ( i ) − i = 2 ∑ n g ( i ) S ( ⌊ i n ⌋ )
Suppose that we can construct a suitable number-theoretic function g g g such that:
∑ i = 1 n ( f ∗ g ) ( i ) \sum_{i=1}^n(f * g)(i) ∑ i = 1 n ( f ∗ g ) ( i ) can be computed quickly;
the prefix sums of g g g can be computed quickly, so that ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) \sum_{i=2}^ng(i)S\left(\left\lfloor\dfrac{n}{i}\right\rfloor\right) ∑ i = 2 n g ( i ) S ( ⌊ i n ⌋ ) can be solved using quotient grouping.
Then we can obtain g ( 1 ) S ( n ) g(1)S(n) g ( 1 ) S ( n ) in a short time.
Note
Regardless of whether the number-theoretic function f f f is multiplicative, as long as a suitable number-theoretic function g g g can be constructed, the Du sieve can be considered for computing the prefix sum of f f f .
For example, consider f ( n ) = i φ ( n ) f(n)=\mathrm{i}\varphi(n) f ( n ) = i φ ( n ) . Clearly, f f f is not multiplicative, but we can take g ( n ) = 1 g(n)=1 g ( n ) = 1 , giving
∑ k = 1 n ( f ∗ g ) ( k ) = i n ( n + 1 ) 2 \sum_{k=1}^n (f*g)(k)=\mathrm{i}\frac{n(n+1)}{2} k = 1 ∑ n ( f ∗ g ) ( k ) = i 2 n ( n + 1 )
The time complexities of computing ∑ k ≤ m ( f ∗ g ) ( k ) \sum_{k\leq m} (f*g)(k) ∑ k ≤ m ( f ∗ g ) ( k ) and ∑ k ≤ m g ( k ) \sum_{k \leq m} g(k) ∑ k ≤ m g ( k ) are both O ( 1 ) O(1) O ( 1 ) , so the Du sieve can be considered.
Time complexity
Let R ( n ) = { ⌊ n k ⌋ : k = 2 , 3 , … , n } R(n)=\left\{\left\lfloor \dfrac{n}{k} \right\rfloor: k=2,3,\dots,n\right\} R ( n ) = { ⌊ k n ⌋ : k = 2 , 3 , … , n } . By the property of quotient grouping, for any m ∈ R ( n ) m\in R(n) m ∈ R ( n ) , we have R ( m ) ⊆ R ( n ) R(m)\subseteq R(n) R ( m ) ⊆ R ( n ) . In other words, with memoization, it is enough to compute k ∈ R ( n ) k\in R(n) k ∈ R ( n ) once for every S ( k ) S(k) S ( k ) to obtain the values of R ( n ) R(n) R ( n ) . The number of these points is ∣ R ( n ) ∣ = O ( n ) |R(n)|=O(\sqrt{n}) ∣ R ( n ) ∣ = O ( n ) .
Suppose the time complexities of computing ∑ i = 1 n ( f ∗ g ) ( i ) \sum_{i=1}^n(f * g)(i) ∑ i = 1 n ( f ∗ g ) ( i ) and ∑ i = 1 n g ( i ) \sum_{i=1}^n g(i) ∑ i = 1 n g ( i ) are both O ( 1 ) O(1) O ( 1 ) . Let the time complexity of computing S ( n ) S(n) S ( n ) be T ( n ) T(n) T ( n ) . Then
T ( n ) = ∑ k ∈ R ( n ) T ( k ) = Θ ( n ) + ∑ k = 1 ⌊ n ⌋ O ( k ) + ∑ k = 2 ⌊ n ⌋ O ( n k ) = O ( ∫ 0 n ( x + n x ) d x ) = O ( n 3 / 4 ) . \begin{aligned}
T(n) & = \sum_{k\in R(n)} T(k)\\
& = \Theta(\sqrt n)+\sum_{k=1}^{\lfloor\sqrt n\rfloor} O(\sqrt k)+\sum_{k=2}^{\lfloor\sqrt n\rfloor} O\left(\sqrt{\dfrac{n}{k}}\right)\\
& = O\left(\int_{0}^{\sqrt n} \left(\sqrt{x} + \sqrt{\dfrac{n}{x}}\right) \mathrm{d}x\right)\\
& = O\left(n^{3/4}\right).
\end{aligned} T ( n ) = k ∈ R ( n ) ∑ T ( k ) = Θ ( n ) + k = 1 ∑ ⌊ n ⌋ O ( k ) + k = 2 ∑ ⌊ n ⌋ O ( k n ) = O ( ∫ 0 n ( x + x n ) d x ) = O ( n 3/4 ) .
If we can preprocess some values S ( k ) S(k) S ( k ) for k = 1 , 2 , … , m k=1,2,\dots,m k = 1 , 2 , … , m , where m ≥ ⌊ n ⌋ m\geq \lfloor\sqrt n\rfloor m ≥ ⌊ n ⌋ , and the preprocessing time complexity is T 0 ( m ) T_0(m) T 0 ( m ) , then T ( n ) T(n) T ( n ) becomes
T ( n ) = T 0 ( m ) + ∑ k ∈ R ( n ) ; k > m T ( k ) = T 0 ( m ) + ∑ k = 1 ⌊ n / m ⌋ O ( n k ) = O ( T 0 ( m ) + ∫ 0 n / m n x d x ) = O ( T 0 ( m ) + n m ) . \begin{aligned}
T(n) & = T_0(m)+\sum_{k\in R(n);k>m} T(k)\\
& = T_0(m)+\sum_{k=1}^{\lfloor n/m \rfloor} O\left(\sqrt{\dfrac{n}{k}}\right)\\
& = O\left(T_0(m)+\int_{0}^{n/m} \sqrt{\dfrac{n}{x}} \mathrm{d}x\right)\\
& = O\left(T_0(m)+\dfrac{n}{\sqrt m}\right).
\end{aligned} T ( n ) = T 0 ( m ) + k ∈ R ( n ) ; k > m ∑ T ( k ) = T 0 ( m ) + k = 1 ∑ ⌊ n / m ⌋ O ( k n ) = O ( T 0 ( m ) + ∫ 0 n / m x n d x ) = O ( T 0 ( m ) + m n ) .
If T 0 ( m ) = O ( m ) T_0(m)=O(m) T 0 ( m ) = O ( m ) , as with a linear sieve, the arithmetic mean-geometric mean inequality shows that m = Θ ( n 2 / 3 ) m=\Theta\left(n^{2/3}\right) m = Θ ( n 2/3 ) is minimized at T ( n ) T(n) T ( n ) , giving O ( n 2 / 3 ) O\left(n^{2/3}\right) O ( n 2/3 ) .
An Incorrect Proof
Suppose the complexity of computing S ( n ) S(n) S ( n ) is T ( n ) T(n) T ( n ) . Then
T ( n ) = Θ ( n ) + O ( ∑ i = 2 ⌊ n ⌋ T ( ⌊ n i ⌋ ) ) T(n)=\Theta\left(\sqrt{n}\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor} T\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\right) T ( n ) = Θ ( n ) + O i = 2 ∑ ⌊ n ⌋ T ( ⌊ i n ⌋ )
T ( ⌊ n i ⌋ ) = Θ ( n i ) + O ( ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) ) = O ( n i ) \begin{aligned}
T\left(\left\lfloor\frac{n}{i}\right\rfloor\right) & = \Theta\left(\sqrt{\frac{n}{i}}\right)+O\left(\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right) \\
& = O\left(\sqrt{\frac{n}{i}}\right)
\end{aligned} T ( ⌊ i n ⌋ ) = Θ ( i n ) + O j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) = O ( i n )
Here, O ( ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) ) O\left(\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\dfrac{n}{ij}\right\rfloor\right)\right) O ( ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) ) is treated as a higher-order infinitesimal and discarded. Therefore,
T ( n ) = Θ ( n ) + O ( ∑ i = 2 ⌊ n ⌋ n i ) = O ( ∑ i = 1 ⌊ n ⌋ n i ) = O ( ∫ 0 n n x d x ) = O ( n 3 / 4 ) \begin{aligned}
T(n) & = \Theta\left(\sqrt{n}\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor} \sqrt{\frac{n}{i}}\right) \\
& = O\left(\sum_{i=1}^{\lfloor\sqrt{n}\rfloor} \sqrt{\frac{n}{i}}\right) \\
& = O\left(\int_{0}^{\sqrt{n}}\sqrt{\frac{n}{x}}\mathrm{d}x\right) \\
& = O\left(n^{3/4}\right)
\end{aligned} T ( n ) = Θ ( n ) + O i = 2 ∑ ⌊ n ⌋ i n = O i = 1 ∑ ⌊ n ⌋ i n = O ( ∫ 0 n x n d x ) = O ( n 3/4 )
Bug
The problem lies in treating the term as a higher-order infinitesimal and discarding it. Substituting T ( ⌊ n i ⌋ ) T\left(\left\lfloor\dfrac{n}{i}\right\rfloor\right) T ( ⌊ i n ⌋ ) into the expression for T ( n ) T(n) T ( n ) gives
T ( n ) = Θ ( n ) + O ( ∑ i = 2 ⌊ n ⌋ n i ) + O ( ∑ i = 2 ⌊ n ⌋ ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) ) = O ( n + ∫ 0 n n x d x ) + O ( ∑ i = 2 ⌊ n ⌋ ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) ) = O ( n 3 / 4 ) + O ( ∑ i = 2 ⌊ n ⌋ ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) ) \begin{aligned}
T(n) & = \Theta\left(\sqrt{n}\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor} \sqrt{\frac{n}{i}}\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor}\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right)\\
& = O\left(\sqrt{n}+\int_{0}^{\sqrt{n}}\sqrt{\frac{n}{x}}\mathrm{d}x\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor}\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right)\\
& = O\left(n^{3/4}\right)+O\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor}\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right)\\
\end{aligned} T ( n ) = Θ ( n ) + O i = 2 ∑ ⌊ n ⌋ i n + O i = 2 ∑ ⌊ n ⌋ j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) = O ( n + ∫ 0 n x n d x ) + O i = 2 ∑ ⌊ n ⌋ j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) = O ( n 3/4 ) + O i = 2 ∑ ⌊ n ⌋ j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ )
Consider the term ∑ i = 2 ⌊ n ⌋ ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) \displaystyle\sum_{i=2}^{\lfloor\sqrt{n}\rfloor}\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right) i = 2 ∑ ⌊ n ⌋ j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) . It is not difficult to see that
∑ i = 2 ⌊ n ⌋ ∑ j = 2 ⌊ n / i ⌋ T ( ⌊ n i j ⌋ ) = Ω ( ∑ i = 2 ⌊ n ⌋ T ( ⌊ n i ⋅ ⌊ n i ⌋ − 1 ⌋ ) ) = Ω ( ∑ i = 2 ⌊ n ⌋ T ( ⌊ n i ⌋ ) ) \begin{aligned}
\sum_{i=2}^{\lfloor\sqrt{n}\rfloor}\sum_{j=2}^{\lfloor\sqrt{n/i}\rfloor} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right) & = \Omega\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor} T\left(\left\lfloor\frac{n}{i}\cdot\left\lfloor\sqrt\frac{n}{i}\right\rfloor^{-1}\right\rfloor\right)\right) \\
& = \Omega\left(\sum_{i=2}^{\lfloor\sqrt{n}\rfloor} T\left(\left\lfloor\sqrt\frac{n}{i}\right\rfloor\right)\right)
\end{aligned} i = 2 ∑ ⌊ n ⌋ j = 2 ∑ ⌊ n / i ⌋ T ( ⌊ ij n ⌋ ) = Ω i = 2 ∑ ⌊ n ⌋ T ( ⌊ i n ⋅ ⌊ i n ⌋ − 1 ⌋ ) = Ω i = 2 ∑ ⌊ n ⌋ T ( ⌊ i n ⌋ )
Since memoization has not been introduced, T ( ⌊ n i ⌋ ) T\left(\left\lfloor\sqrt{\dfrac{n}{i}}\right\rfloor\right) T ( ⌊ i n ⌋ ) in the expression above is still Ω ( ( n i ) 1 / 4 ) \Omega\left(\left(\dfrac{n}{i}\right)^{1/4}\right) Ω ( ( i n ) 1/4 ) , so the supposedly higher-order infinitesimal term cannot be discarded.
In fact, the sublinear time complexity of the Du sieve is guaranteed by memoization. Only after memoization is used can we ensure that the multiple-summation term does not appear.
Examples
Problem 1
P4213 [Template] Du Sieve (Sum)
Find the values of S 1 ( n ) = ∑ i = 1 n μ ( i ) S_1(n)= \sum_{i=1}^{n} \mu(i) S 1 ( n ) = ∑ i = 1 n μ ( i ) and S 2 ( n ) = ∑ i = 1 n φ ( i ) S_2(n)= \sum_{i=1}^{n} \varphi(i) S 2 ( n ) = ∑ i = 1 n φ ( i ) , where 1 ≤ n < 2 31 1\leq n<2^{31} 1 ≤ n < 2 31 .
Prefix Sum of the Möbius Function
We know that
ϵ = [ n = 1 ] = μ ∗ 1 = ∑ d ∣ n μ ( d ) \epsilon = [n=1] = \mu * 1 = \sum_{d \mid n} \mu(d) ϵ = [ n = 1 ] = μ ∗ 1 = d ∣ n ∑ μ ( d )
S 1 ( n ) = ∑ i = 1 n ϵ ( i ) − ∑ i = 2 n S 1 ( ⌊ n i ⌋ ) = 1 − ∑ i = 2 n S 1 ( ⌊ n i ⌋ ) \begin{aligned}
S_1(n) & =\sum_{i=1}^n \epsilon (i)-\sum_{i=2}^n S_1 \left(\left\lfloor \frac n i \right\rfloor\right) \\
& = 1-\sum_{i=2}^n S_1\left(\left\lfloor \frac n i \right\rfloor\right)
\end{aligned} S 1 ( n ) = i = 1 ∑ n ϵ ( i ) − i = 2 ∑ n S 1 ( ⌊ i n ⌋ ) = 1 − i = 2 ∑ n S 1 ( ⌊ i n ⌋ )
See the section on time complexity for the derivation.
For large values, the corresponding values should be stored in a map/unordered_map, so that previously computed results can be used directly later.
Prefix Sum of the Euler Totient Function
The Du sieve can of course also be used to find the prefix sum of φ ( x ) \varphi (x) φ ( x ) , but Möbius inversion gives a better method.
Möbius Inversion
∑ i = 1 n ∑ j = 1 n [ gcd ( i , j ) = 1 ] = ∑ i = 1 n ∑ j = 1 n ∑ d ∣ i , d ∣ j μ ( d ) = ∑ d = 1 n μ ( d ) ⌊ n d ⌋ 2 \begin{aligned}
\sum_{i=1}^n \sum_{j=1}^n [\gcd(i,j)=1] & =\sum_{i=1}^n \sum_{j=1}^n \sum_{d \mid i,d \mid j} \mu(d) \\
& =\sum_{d=1}^n \mu(d) {\left\lfloor \frac n d \right\rfloor}^2
\end{aligned} i = 1 ∑ n j = 1 ∑ n [ g cd( i , j ) = 1 ] = i = 1 ∑ n j = 1 ∑ n d ∣ i , d ∣ j ∑ μ ( d ) = d = 1 ∑ n μ ( d ) ⌊ d n ⌋ 2
Since the problem asks for ∑ i = 1 n ∑ j = 1 i [ gcd ( i , j ) = 1 ] \sum_{i=1}^n \sum_{j=1}^i [\gcd(i,j)=1] ∑ i = 1 n ∑ j = 1 i [ g cd( i , j ) = 1 ] , we exclude the case i = 1 , j = 1 i=1,j=1 i = 1 , j = 1 and divide the result by 2 2 2 .
It can be seen that once the prefix sum of the Möbius function is known, the prefix sum of the Euler totient function can be computed quickly. The time complexity is O ( n 2 3 ) O\left(n^{\frac 2 3}\right) O ( n 3 2 ) .
Du Sieve
Find S ( n ) = ∑ i = 1 n φ ( i ) S(n)=\sum_{i=1}^n\varphi(i) S ( n ) = ∑ i = 1 n φ ( i ) .
Similarly, φ ∗ 1 = id \varphi * 1=\operatorname{id} φ ∗ 1 = id , so
S ( n ) = ∑ i = 1 n i − ∑ i = 2 n S ( ⌊ n i ⌋ ) = 1 2 n ( n + 1 ) − ∑ i = 2 n S ( ⌊ n i ⌋ ) \begin{aligned}
S(n) & =\sum_{i=1}^n i - \sum_{i=2}^n S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\frac{1}{2}n(n+1) - \sum_{i=2}^n S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned} S ( n ) = i = 1 ∑ n i − i = 2 ∑ n S ( ⌊ i n ⌋ ) = 2 1 n ( n + 1 ) − i = 2 ∑ n S ( ⌊ i n ⌋ )
Implementation
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
constexpr int MAXN = 2000010 ;
long long T, n, pri[MAXN], cur, mu[MAXN], sum_mu[MAXN];
bool vis[MAXN];
map<long long , long long > mp_mu;
long long S_mu (long long x) {
if (x < MAXN) return sum_mu[x];
if (mp_mu[x]) return mp_mu[x];
long long ret = (long long )1 ;
for (long long i = 2 , j; i <= x; i = j + 1 ) {
j = x / (x / i);
ret -= S_mu (x / i) * (j - i + 1 );
}
return mp_mu[x] = ret;
}
long long S_phi (long long x) {
long long ret = (long long )0 ;
long long j;
for (long long i = 1 ; i <= x; i = j + 1 ) {
j = x / (x / i);
ret += (S_mu (j) - S_mu (i - 1 )) * (x / i) * (x / i);
}
return (ret - 1 ) / 2 + 1 ;
}
int main () {
cin.tie (nullptr )->sync_with_stdio (false );
cin >> T;
mu[1 ] = 1 ;
for (int i = 2 ; i < MAXN; i++) {
if (!vis[i]) {
pri[++cur] = i;
mu[i] = -1 ;
}
for (int j = 1 ; j <= cur && i * pri[j] < MAXN; j++) {
vis[i * pri[j]] = true ;
if (i % pri[j])
mu[i * pri[j]] = -mu[i];
else {
mu[i * pri[j]] = 0 ;
break ;
}
}
}
for (int i = 1 ; i < MAXN; i++)
sum_mu[i] = sum_mu[i - 1 ] + mu[i];
while (T--) {
cin >> n;
cout << S_phi (n) << ' ' << S_mu (n) << '\n' ;
}
return 0 ;
}
Problem 2
Luogu P3768, “A Simple Math Problem”
In essence, compute
∑ i = 1 n ∑ j = 1 n i ⋅ j ⋅ gcd ( i , j ) ( m o d p ) \sum_{i=1}^n\sum_{j=1}^ni\cdot j\cdot\gcd(i,j)\pmod p i = 1 ∑ n j = 1 ∑ n i ⋅ j ⋅ g cd( i , j ) ( mod p )
where n ≤ 10 10 , 5 × 10 8 ≤ p ≤ 1.1 × 10 9 n\leq 10^{10},5\times 10^8\leq p\leq 1.1\times 10^9 n ≤ 1 0 10 , 5 × 1 0 8 ≤ p ≤ 1.1 × 1 0 9 , and p p p is prime.
Using φ ∗ 1 = id \varphi * 1=\operatorname{id} φ ∗ 1 = id and Möbius inversion, this becomes
∑ d = 1 n F 2 ( ⌊ n d ⌋ ) ⋅ d 2 φ ( d ) \sum_{d=1}^nF^2\left(\left\lfloor\frac{n}{d}\right\rfloor\right)\cdot d^2\varphi(d) d = 1 ∑ n F 2 ( ⌊ d n ⌋ ) ⋅ d 2 φ ( d )
where F ( n ) = 1 2 n ( n + 1 ) F(n)=\dfrac{1}{2}n(n+1) F ( n ) = 2 1 n ( n + 1 ) .
Apply quotient grouping to ∑ d = 1 n F ( ⌊ n d ⌋ ) 2 \sum_{d=1}^nF\left(\left\lfloor\dfrac{n}{d}\right\rfloor\right)^2 ∑ d = 1 n F ( ⌊ d n ⌋ ) 2 , and use the Du sieve to handle the prefix sum of d 2 φ ( d ) d^2\varphi(d) d 2 φ ( d ) :
f ( n ) = n 2 φ ( n ) = ( id 2 φ ) ( n ) f(n)=n^2\varphi(n)=(\operatorname{id}^2\varphi)(n) f ( n ) = n 2 φ ( n ) = ( id 2 φ ) ( n )
S ( n ) = ∑ i = 1 n f ( i ) = ∑ i = 1 n ( id 2 φ ) ( i ) S(n)=\sum_{i=1}^nf(i)=\sum_{i=1}^n(\operatorname{id}^2\varphi)(i) S ( n ) = i = 1 ∑ n f ( i ) = i = 1 ∑ n ( id 2 φ ) ( i )
We need to construct a multiplicative function g g g such that f × g f\times g f × g and g g g can be summed quickly.
The prefix sum of φ \varphi φ alone can be handled by applying the Du sieve to φ ∗ 1 \varphi * 1 φ ∗ 1 , but here f f f has an additional id 2 \operatorname{id}^2 id 2 . We therefore convolve by an id 2 \operatorname{id}^2 id 2 to turn it into a constant:
S ( n ) = ∑ i = 1 n ( ( id 2 φ ) ∗ id 2 ) ( i ) − ∑ i = 2 n id 2 ( i ) S ( ⌊ n i ⌋ ) S(n)=\sum_{i=1}^n\left(\left(\operatorname{id}^2\varphi\right) * \operatorname{id}^2\right)(i)-\sum_{i=2}^n\operatorname{id}^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) S ( n ) = i = 1 ∑ n ( ( id 2 φ ) ∗ id 2 ) ( i ) − i = 2 ∑ n id 2 ( i ) S ( ⌊ i n ⌋ )
Simplifying the convolution gives
( ( id 2 φ ) ∗ id 2 ) ( i ) = ∑ d ∣ i ( id 2 φ ) ( d ) id 2 ( i d ) = ∑ d ∣ i d 2 φ ( d ) ( i d ) 2 = ∑ d ∣ i i 2 φ ( d ) = i 2 ∑ d ∣ i φ ( d ) = i 2 ( φ ∗ 1 ) ( i ) = i 3 \begin{aligned}
((\operatorname{id}^2\varphi)* \operatorname{id}^2)(i) & =\sum_{d \mid i}\left(\operatorname{id}^2\varphi\right)(d)\operatorname{id}^2\left(\frac{i}{d}\right) \\
& =\sum_{d \mid i}d^2\varphi(d)\left(\frac{i}{d}\right)^2 \\
& =\sum_{d \mid i}i^2\varphi(d)=i^2\sum_{d \mid i}\varphi(d) \\
& =i^2(\varphi*1)(i)=i^3
\end{aligned} (( id 2 φ ) ∗ id 2 ) ( i ) = d ∣ i ∑ ( id 2 φ ) ( d ) id 2 ( d i ) = d ∣ i ∑ d 2 φ ( d ) ( d i ) 2 = d ∣ i ∑ i 2 φ ( d ) = i 2 d ∣ i ∑ φ ( d ) = i 2 ( φ ∗ 1 ) ( i ) = i 3
Simplifying S ( n ) S(n) S ( n ) once more:
S ( n ) = ∑ i = 1 n ( ( id 2 φ ) ∗ id 2 ) ( i ) − ∑ i = 2 n id 2 ( i ) S ( ⌊ n i ⌋ ) = ∑ i = 1 n i 3 − ∑ i = 2 n i 2 S ( ⌊ n i ⌋ ) = ( 1 2 n ( n + 1 ) ) 2 − ∑ i = 2 n i 2 S ( ⌊ n i ⌋ ) \begin{aligned}
S(n) & =\sum_{i=1}^n\left((\operatorname{id}^2\varphi)* \operatorname{id}^2\right)(i)-\sum_{i=2}^n\operatorname{id}^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\sum_{i=1}^ni^3-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\left(\frac{1}{2}n(n+1)\right)^2-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
\end{aligned} S ( n ) = i = 1 ∑ n ( ( id 2 φ ) ∗ id 2 ) ( i ) − i = 2 ∑ n id 2 ( i ) S ( ⌊ i n ⌋ ) = i = 1 ∑ n i 3 − i = 2 ∑ n i 2 S ( ⌊ i n ⌋ ) = ( 2 1 n ( n + 1 ) ) 2 − i = 2 ∑ n i 2 S ( ⌊ i n ⌋ )
The problem can then be solved by quotient grouping.
Implementation
#include <cmath>
#include <iostream>
#include <map>
using namespace std;
constexpr int N = 5e6 , NP = 5e6 , SZ = N;
long long n, P, inv2, inv6, s[N];
int phi[N], p[NP], cnt, pn;
bool bp[N];
map<long long , long long > s_map;
long long ksm (long long a, long long m) {
long long res = 1 ;
while (m) {
if (m & 1 ) res = res * a % P;
a = a * a % P, m >>= 1 ;
}
return res;
}
void prime_work (int k) {
bp[0 ] = bp[1 ] = true , phi[1 ] = 1 ;
for (int i = 2 ; i <= k; i++) {
if (!bp[i]) p[++cnt] = i, phi[i] = i - 1 ;
for (int j = 1 ; j <= cnt && i * p[j] <= k; j++) {
bp[i * p[j]] = true ;
if (i % p[j] == 0 ) {
phi[i * p[j]] = phi[i] * p[j];
break ;
} else
phi[i * p[j]] = phi[i] * phi[p[j]];
}
}
for (int i = 1 ; i <= k; i++)
s[i] = (1ll * i * i % P * phi[i] % P + s[i - 1 ]) % P;
}
long long s3 (long long k) {
return k %= P, (k * (k + 1 ) / 2 ) % P * ((k * (k + 1 ) / 2 ) % P) % P;
}
long long s2 (long long k) {
return k %= P, k * (k + 1 ) % P * (k * 2 + 1 ) % P * inv6 % P;
}
long long calc (long long k) {
if (k <= pn) return s[k];
if (s_map[k]) return s_map[k];
long long res = s3 (k), pre = 1 , cur;
for (long long i = 2 , j; i <= k; i = j + 1 )
j = k / (k / i), cur = s2 (j),
res = (res - calc (k / i) * (cur - pre) % P) % P, pre = cur;
return s_map[k] = (res + P) % P;
}
long long solve () {
long long res = 0 , pre = 0 , cur;
for (long long i = 1 , j; i <= n; i = j + 1 ) {
j = n / (n / i);
cur = calc (j);
res = (res + (s3 (n / i) * (cur - pre)) % P) % P;
pre = cur;
}
return (res + P) % P;
}
int main () {
cin.tie (nullptr )->sync_with_stdio (false );
cin >> P >> n;
inv2 = ksm (2 , P - 2 ), inv6 = ksm (6 , P - 2 );
pn = (long long )pow (n, 0.666667 );
prime_work (pn);
cout << solve ();
return 0 ;
}
References
Zhizhou Ren, 2016, Several Methods for Summing Multiplicative Functions , a paper by a candidate for the Chinese National Olympiad in Informatics team.
Analysis of the time and space complexity of the Du sieve - riteme.site