# [template] Sum

## General idea of the topic

Please φ Prefix and sum of functions μ Prefix and of the function.
(Euler function and Mobius function respectively)

## 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;
}


Tags: partitioning

Posted on Tue, 02 Nov 2021 15:43:57 -0400 by zmoerf