[template] Sum
Title Link: luogu P4213
General idea of the topic
Please φ Prefix and sum of functions μ Prefix and of the function.
(Euler function and Mobius function respectively)
thinking
Pre knowledge
Integral function: for two coprime numbers \ (x,y \), \ (f(xy)=f(x)f(y) \), then \ (f \) is an integral function.
Complete integral function: for any two integers \ (x,y \), \ (f(xy)=f(x)f(y) \), then \ (f \) is a complete integral function.
Some integrable functions: \ (\ varphi,\mu,d,\sigma \)
(Euler function, Mobius function, number of divisors, sum of divisors)
Some fully integrable functions: \ (\ epsilon,I,id \)
\(\epsilon(n)=[n=1],I(n)=1,id(n)=n\)
Dirichlet convolution:
There are two functions \ (f,g \), and their Dirichlet convolution: \ ((f*g)(n)=\sum\limits_{d|n}f(d)g(\dfrac{n}{d}) \)
It is not difficult to see that it satisfies the commutative law and the associative law.
Then the unit element is \ (\ epsilon \).
Then there are some properties: (according to the definition, it is not difficult to see a simple push)
\(\mu*I=\epsilon\)
\(\varphi*I=id\)
\(\mu*id=\varphi\)
Mo fan:
If \ (g(n)=\sum\limits_{d|n}f(d) \)
Then \ (f(n)=\sum\limits_{d|n}\mu(d)g(\dfrac{n}{d}) \)
The proof of this place can actually be \ (\ mu*I=\epsilon \)
The given condition is equivalent to \ (g=f*I \)
Then \ (g*\mu=f*I*\mu=f*\epsilon=f \).
Du Jiao sieve
Du Jiao sieve is the prefix and \ (sum (n) = \ sum \ limits {I = 1} ^ NF (I) \) used for quadrature functions
Consider finding another integral function \ (g \) to find their Dirichlet convolution:
\(\sum\limits_{i=1}^n(f*g)(i)\)
\(=\sum\limits_{i=1}^n\sum\limits_{d|n}f(d)g(\dfrac{i}{d})\)
\(=\sum\limits_{d=1}^ng(d)\sum\limits_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(i)\)
\(=\sum\limits_{d=1}^ng(d)sum(\left\lfloor\dfrac{n}{d}\right\rfloor)\)
Then consider \ (g(1)sum(n) \), according to the prefix and:
\(=\sum\limits_{i=1}^ng(i)sum(\left\lfloor\dfrac{n}{i}\right\rfloor)-\sum\limits_{i=2}^ng(i)sum(\left\lfloor\dfrac{n}{i}\right\rfloor)\)
\(=\sum\limits_{i=1}^n(f*g)(i)-\sum\limits_{i=2}^ng(i)sum(\left\lfloor\dfrac{n}{i}\right\rfloor)\)
Then this formula is the one we need to use.
What's the use? For each \ (f \) you require, if you can find a suitable \ (g \), it can be multiplied by \ (f \) and \ (g \) can be used.
For the example of this problem, \ (\ mu*I=\epsilon \), so the prefix of \ (\ epsilon \) and \ (1 \) are on the left, and then you can divide the blocks by integer \ (O(\sqrt{n}) \) on the right.
Then \ (\ varphi*I=id \), then the prefix sum of \ (id \) on the left is \ (\ dfrac{(1+n)n}{2} \), and the right is divided into blocks.
(then the two right sides \ (g(i) \) can also be calculated with the prefix sum because they are integer division blocks. Because they are \ (I \), they are \ (r-l+1 \), that is, the size of the block)
Then you can preprocess the results within \ (n^{\frac{2}{3} \), and the complexity can be reduced to \ (O(n^{\frac{2}{3}) \).
(then you can use \ (map \) to make a little memory)
code
#include<map> #include<cstdio> #define ll long long using namespace std; //const int Maxn = 1664511; const int Maxn = 2000000; int T, np[Maxn + 1], prime[Maxn + 1]; int miu[Maxn + 1], x; ll phi[Maxn + 1]; map <int, int> ans_miu; map <int, ll> ans_phi; void init() {//Part of preprocessing n^{2/3} miu[1] = phi[1] = 1; for (int i = 2; i <= Maxn; i++) { if (!np[i]) { prime[++prime[0]] = i; miu[i] = -1; phi[i] = i - 1; } for (int j = 1; j <= prime[0] && i * prime[j] <= Maxn; j++) { if (i % prime[j]) miu[i * prime[j]] = -miu[i], phi[i * prime[j]] = phi[i] * (prime[j] - 1), np[i * prime[j]] = prime[j]; else { miu[i * prime[j]] = 0, phi[i * prime[j]] = phi[i] * prime[j], np[i * prime[j]] = prime[j]; break; } } } for (int i = 1; i <= Maxn; i++)//Prefix with miu[i] += miu[i - 1], phi[i] += phi[i - 1]; } ll get_phi(int x) { if (x <= Maxn) return phi[x]; if (ans_phi[x]) return ans_phi[x]; ll re = 1ll * (1ll + x) * x / 2;//Prefix and of id function for (ll l = 2, r; l <= x; l = r + 1) { r = x / (x / l); re -= 1ll * (r - l + 1) * get_phi(x / l); } return ans_phi[x] = re; } int get_miu(int x) { if (x <= Maxn) return miu[x]; if (ans_miu[x]) return ans_miu[x]; ll re = 1;//ϵ Prefix and of function for (ll l = 2, r; l <= x; l = r + 1) { r = x / (x / l); re -= 1ll * (r - l + 1) * get_miu(x / l); } return ans_miu[x] = re; } int main() { init(); scanf("%d", &T); while (T--) { scanf("%d", &x); printf("%llu %d\n", get_phi(x), get_miu(x)); } return 0; }