Powerful Number Sieve
Definition
Powerful Number (abbreviated as PN) sieve is similar to the Dirichlet convolution sieve, or rather an extension of it, used to compute the prefix sum of certain multiplicative functions.
Requirements:
- There exists a function \(g\) satisfying:
- \(g\) is a multiplicative function.
- The prefix sum of \(g\) is easy to compute.
- For prime \(p\), \(g(p) = f(p)\).
Suppose we want to compute the prefix sum \(F(n) = \sum_{i=1}^{n} f(i)\) of a multiplicative function \(f\).
Powerful Number
Definition: For a positive integer \(n\), let its prime factorization be \(n = \prod_{i=1}^{m} p_{i}^{e_{i}}\). \(n\) is a PN if and only if \(\forall 1 \le i \le m, e_{i} > 1\).
Property 1: All PNs can be expressed in the form \(a^{2}b^{3}\).
Proof: If \(e_i\) is even, merge \(p_{i}^{e_{i}}\) into \(a^{2}\); if \(e_i\) is odd, first merge \(p_{i}^{3}\) into \(b^{3}\), then merge \(p_{i}^{e_{i}-3}\) into \(a^{2}\).
Property 2: There are at most \(O(\sqrt{n})\) PNs not exceeding \(n\).
Proof: Consider enumerating \(a\), then count the number of \(b\) satisfying the condition. The approximate number of PNs is
How to find all PNs not exceeding \(n\)? Use a linear sieve to find all primes up to \(\sqrt{n}\), then perform a DFS to search for exponents of these primes. Since there are at most \(O(\sqrt{n})\) PNs not exceeding \(n\), the search will be performed at most \(O(\sqrt{n})\) times.
PN Sieve
First, construct a multiplicative function \(g\) whose prefix sum is easy to compute, and such that for prime \(p\), \(g(p) = f(p)\). Denote \(G(n) = \sum_{i=1}^{n} g(i)\).
Then, define the function \(h = f / g\), where \(/\) denotes Dirichlet convolution division. From the properties of Dirichlet convolution, \(h\) is also a multiplicative function, so \(h(1) = 1\). We have \(f = g * h\), where \(*\) denotes Dirichlet convolution.
For prime \(p\), \(f(p) = g(1)h(p) + g(p)h(1) = h(p) + g(p) \implies h(p) = 0\). From \(h(p)=0\) and the multiplicativity of \(h\), it follows that \(h(n) = 0\) for non-PN numbers \(n\), meaning \(h\) takes non-zero values only at PNs.
Now, from \(f = g * h\), we have
Find all PNs within \(O(\sqrt{n})\) and compute all non-zero values of \(h\). To compute the non-zero values of \(h\), it suffices to compute \(h(p^c)\) for all prime powers, then use the multiplicativity of \(h\) to derive all non-zero values. For each non-zero value \(d\), compute \(h(d)G\left(\left\lfloor \dfrac{n}{d} \right\rfloor\right)\) and accumulate to obtain \(F(n)\).
Now consider computing \(h(p^c)\). There are two methods: one is to derive a formula for \(h(p^c)\) that depends only on \(p\) and \(c\), then compute using the formula; the other is to use \(f = g * h\), which gives \(f(p^c) = \sum_{i=0}^c g(p^i)h(p^{c-i})\). Rearranging yields \(h(p^c) = f(p^c) - \sum_{i=1}^{c}g(p^i)h(p^{c-i})\). Now we can enumerate primes \(p\) and exponents \(c\) to compute all \(h(p^c)\).
Procedure
- Construct \(g\)
- Construct a method to compute \(G\) quickly
- Compute \(h(p^c)\)
- Search for PNs, accumulating the answer during the search
- Obtain the result
For step 3, you can compute directly using a formula, precompute a table via enumeration, or derive on-the-fly during the search.
Complexity Analysis
Using the second method to compute \(h(p^c)\) as an example, the analysis can be divided into computing \(h(p^c)\) and the search part.
For the first part, the number of primes up to \(O(\sqrt{n})\) is \(O\left(\dfrac{\sqrt{n}}{\log n}\right)\). For each prime \(p\), the exponent \(c\) is at most \(\log n\), and computing \(h(p^c)\) requires \((c - 1)\) iterations. Thus, the time complexity of the first part is \(O\left(\dfrac{\sqrt{n}}{\log n} \cdot \log n \cdot \log n\right) = O(\sqrt{n}\log{n})\), which is a loose upper bound. Depending on the problem, additional optimizations can be applied to reduce this complexity.
For the search part, since there are at most \(O(\sqrt{n})\) PNs not exceeding \(n\), the search is performed at most \(O(\sqrt{n})\) times. For each PN, the time complexity depends on the method used to compute \(G\). For example, if computing \(G\left(\left\lfloor \dfrac{n}{d}\right\rfloor\right)\) takes \(O(1)\) time, the complexity of the second part is \(O(\sqrt{n})\).
In particular, if the Dirichlet convolution sieve is used to compute \(G\left(\left\lfloor \dfrac{n}{d}\right\rfloor\right)\), the time complexity of the second part becomes that of the Dirichlet convolution sieve, i.e., \(O(n^{\frac{2}{3}})\). This is because if \(G(n)\) is computed once beforehand, optimized with a linear sieve, and larger values are stored in a data structure supporting fast random access (like std::map or std::unordered_map in C++), then all \(G\left(\left\lfloor \dfrac{n}{d}\right\rfloor\right)\) used during the Dirichlet convolution sieve are either recorded in the linear sieve or in the std::map. This can be verified directly with code.
For space complexity, the bottleneck is storing \(h(p^c)\). If a two-dimensional array \(a\) is used, where \(a_{i,j}\) represents \(h(p_i^j)\), the space complexity is \(O\left(\dfrac{\sqrt{n}}{\log n} \cdot \log n\right) = O(\sqrt{n})\).
Example Problems
Luogu P5325【Template】Min_25 Sieve
Problem: Given a multiplicative function \(f(p^k) = p^k(p^k-1)\), compute \(\sum_{i=1}^{n} f(i)\).
We have \(f(p) = p(p-1) = \operatorname{id}(p)\varphi(p)\). Construct \(g(n) = \operatorname{id}(n)\varphi(n)\).
Consider using the Dirichlet convolution sieve to compute \(G(n)\). From \((\operatorname{id}\cdot \varphi) * \operatorname{id} = \operatorname{id}_2\), we get \(G(n)= \sum_{i=1}^{n} i^2 - \sum_{d=2}^{n} d \cdot G\left(\left\lfloor \dfrac{n}{d} \right\rfloor\right)\).
Then \(h(p^k)\) can be computed by enumeration, which we will not elaborate here.
Alternatively, we can derive a formula for \(h(p^k)\) that depends only on \(p\) and \(k\), as follows:
Using \(h(p) = 0\) and summing, we obtain \(h(p^k) = (k-1)(p-1)p^k\).
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
「LOJ #6053」Simple Function
Given \(f(n)\):
We have:
Construct \(g\) as
It can be verified that \(g(p) = f(p)\) and \(g\) is multiplicative.
Now consider computing \(G(n)\).
Let \(S_1(n) = \sum_{i=1}^{n} \varphi(i)\) and \(S_2(n) = \sum_{i=1}^{n} \varphi(2i)\). Then \(G(n) = S_1(n) + 2S_2\left(\left\lfloor \dfrac{n}{2} \right\rfloor\right)\).
When \(2 \mid n\), we have
When \(2 \nmid n\), we have
In summary, \(S_2(n) = S_1(n) + S_2\left(\left\lfloor \dfrac{n}{2} \right\rfloor\right)\).
\(S_1\) can be computed using the Dirichlet convolution sieve, and \(S_2\) can be computed directly using the recurrence. Thus \(G\) can also be computed.
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | |
Exercises
References
- 破壁人五号 - A brief explanation of Powerful number sieve
- command_block - Dirichlet convolution sieve (+ Bell series + powerful number)
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用