Перейти до основного вмісту

Кількість дільників / сума дільників

У цій статті ми обговоримо, як обчислити кількість дільників d(n)d(n) та суму дільників σ(n)\sigma(n) заданого числа nn.

Коли підходить цей алгоритм?
  • Чи потрібно обчислити кількість d(n)d(n) або суму σ(n)\sigma(n) дільників числа через його розклад на прості множники?
  • Чи запитів небагато, щоб факторизація кожного nn за O(n)O(\sqrt{n}) була прийнятною? (якщо потрібно d(n)d(n) чи σ(n)\sigma(n) для всіх nn до NN одразу → Решето Ератосфена)
  • Якщо саме отримання розкладу на множники складне (велике nn) — (→ Факторизація цілих чисел)?

Кількість дільників

Має бути очевидно, що розклад на прості множники дільника dd є підмножиною розкладу на прості множники числа nn, наприклад 6=236 = 2 \cdot 3 є дільником 60=223560 = 2^2 \cdot 3 \cdot 5. Тож нам потрібно лише знайти всі різні підмножини розкладу на прості множники числа nn.

Зазвичай кількість підмножин дорівнює 2x2^x для множини з xx елементів. Проте це вже не так, якщо у множині є повторювані елементи. У нашому випадку деякі прості множники можуть з'являтися кілька разів у розкладі на прості множники числа nn.

Якщо простий множник pp з'являється ee разів у розкладі на прості множники числа nn, то ми можемо використати множник pp до ee разів у підмножині. Це означає, що ми маємо e+1e+1 варіантів вибору.

Тому якщо розклад на прості множники числа nn має вигляд p1e1p2e2pkekp_1^{e_1} \cdot p_2^{e_2} \cdots p_k^{e_k}, де pip_i — різні прості числа, то кількість дільників дорівнює:

d(n)=(e1+1)(e2+1)(ek+1)d(n) = (e_1 + 1) \cdot (e_2 + 1) \cdots (e_k + 1)

Про це можна думати в такий спосіб:

  • Якщо є лише один різний простий дільник n=p1e1n = p_1^{e_1}, то очевидно, що дільників e1+1e_1 + 1 (1,p1,p12,,p1e11, p_1, p_1^2, \dots, p_1^{e_1}).

  • Якщо є два різних простих дільники n=p1e1p2e2n = p_1^{e_1} \cdot p_2^{e_2}, то всі дільники можна розташувати у вигляді таблиці.

1p2p22p2e211p2p22p2e2p1p1p1p2p1p22p1p2e2p12p12p12p2p12p22p12p2e2p1e1p1e1p1e1p2p1e1p22p1e1p2e2\begin{array}{c|ccccc} & 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\\hline 1 & 1 & p_2 & p_2^2 & \dots & p_2^{e_2} \\\\ p_1 & p_1 & p_1 \cdot p_2 & p_1 \cdot p_2^2 & \dots & p_1 \cdot p_2^{e_2} \\\\ p_1^2 & p_1^2 & p_1^2 \cdot p_2 & p_1^2 \cdot p_2^2 & \dots & p_1^2 \cdot p_2^{e_2} \\\\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\\\ p_1^{e_1} & p_1^{e_1} & p_1^{e_1} \cdot p_2 & p_1^{e_1} \cdot p_2^2 & \dots & p_1^{e_1} \cdot p_2^{e_2} \\\\ \end{array}

Тож кількість дільників тривіально дорівнює (e1+1)(e2+1)(e_1 + 1) \cdot (e_2 + 1).

  • Подібне міркування можна провести, якщо різних простих множників більше ніж два.
long long numberOfDivisors(long long num) {
long long total = 1;
for (int i = 2; (long long)i * i <= num; i++) {
if (num % i == 0) {
int e = 0;
do {
e++;
num /= i;
} while (num % i == 0);
total *= e + 1;
}
}
if (num > 1) {
total *= 2;
}
return total;
}

Сума дільників

Ми можемо скористатися тим самим міркуванням, що й у попередньому розділі.

  • Якщо є лише один різний простий дільник n=p1e1n = p_1^{e_1}, то сума дорівнює:
1+p1+p12++p1e1=p1e1+11p111 + p_1 + p_1^2 + \dots + p_1^{e_1} = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1}
  • Якщо є два різних простих дільники n=p1e1p2e2n = p_1^{e_1} \cdot p_2^{e_2}, то ми можемо скласти ту саму таблицю, що й раніше. Єдина відмінність полягає в тому, що тепер ми хочемо обчислити суму, а не підрахувати кількість елементів. Легко бачити, що суму всіх комбінацій можна виразити як:
(1+p1+p12++p1e1)(1+p2+p22++p2e2)\left(1 + p_1 + p_1^2 + \dots + p_1^{e_1}\right) \cdot \left(1 + p_2 + p_2^2 + \dots + p_2^{e_2}\right) =p1e1+11p11p2e2+11p21= \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1}
  • У загальному випадку для n=p1e1p2e2pkekn = p_1^{e_1} \cdot p_2^{e_2} \cdots p_k^{e_k} ми отримуємо формулу:
σ(n)=p1e1+11p11p2e2+11p21pkek+11pk1\sigma(n) = \frac{p_1^{e_1 + 1} - 1}{p_1 - 1} \cdot \frac{p_2^{e_2 + 1} - 1}{p_2 - 1} \cdots \frac{p_k^{e_k + 1} - 1}{p_k - 1}
long long SumOfDivisors(long long num) {
long long total = 1;

for (int i = 2; (long long)i * i <= num; i++) {
if (num % i == 0) {
int e = 0;
do {
e++;
num /= i;
} while (num % i == 0);

long long sum = 0, pow = 1;
do {
sum += pow;
pow *= i;
} while (e-- > 0);
total *= sum;
}
}
if (num > 1) {
total *= (1 + num);
}
return total;
}

Мультиплікативні функції

Мультиплікативна функція — це функція f(x)f(x), яка задовольняє

f(ab)=f(a)f(b)f(a \cdot b) = f(a) \cdot f(b)

якщо aa і bb взаємно прості.

І d(n)d(n), і σ(n)\sigma(n) є мультиплікативними функціями.

Мультиплікативні функції мають величезне розмаїття цікавих властивостей, які можуть бути дуже корисними у задачах теорії чисел. Наприклад, згортка Діріхле двох мультиплікативних функцій також є мультиплікативною.

Задачі для практики

Відеоматеріали