Кількість дільників / сума дільників
У цій статті ми обговоримо, як обчислити кількість дільників та суму дільників заданого числа .
- Чи потрібно обчислити кількість або суму дільників числа через його розклад на прості множники?
- Чи запитів небагато, щоб факторизація кожного за була прийнятною? (якщо потрібно чи для всіх до одразу → Решето Ератосфена)
- Якщо саме отримання розкладу на множники складне (велике ) — (→ Факторизація цілих чисел)?
Кількість дільників
Має бути очевидно, що розклад на прості множники дільника є підмножиною розкладу на прості множники числа , наприклад є дільником . Тож нам потрібно лише знайти всі різні підмножини розкладу на прості множники числа .
Зазвичай кількість підмножин дорівнює для множини з елементів. Проте це вже не так, якщо у множині є повторювані елементи. У нашому випадку деякі прості множники можуть з'являтися кілька разів у розкладі на прості множники числа .
Якщо простий множник з'являється разів у розкладі на прості множники числа , то ми можемо використати множник до разів у підмножині. Це означає, що ми маємо варіантів вибору.
Тому якщо розклад на прості множники числа має вигляд , де — різні прості числа, то кількість дільників дорівнює:
Про це можна думати в такий спосіб:
-
Якщо є лише один різний простий дільник , то очевидно, що дільників ().
-
Якщо є два різних простих дільники , то всі дільники можна розташувати у вигляді таблиці.
Тож кількість дільників тривіально дорівнює .
- Подібне міркування можна провести, якщо різних простих множників більше ніж два.
- C++
- Python
- TypeScript
- Go
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;
}
def number_of_divisors(num: int) -> int:
total = 1
i = 2
while i * i <= num:
if num % i == 0:
e = 0
# Підраховуємо степінь простого множника i
while num % i == 0:
e += 1
num //= i
total *= e + 1
i += 1
if num > 1:
# Залишок — простий множник у першому степені
total *= 2
return total
function numberOfDivisors(num: bigint): bigint {
let total = 1n;
for (let i = 2n; i * i <= num; i++) {
if (num % i === 0n) {
let e = 0n;
// Підраховуємо степінь простого множника i
do {
e++;
num /= i;
} while (num % i === 0n);
total *= e + 1n;
}
}
if (num > 1n) {
// Залишок — простий множник у першому степені
total *= 2n;
}
return total;
}
func numberOfDivisors(num int64) int64 {
var total int64 = 1
for i := int64(2); i*i <= num; i++ {
if num%i == 0 {
var e int64 = 0
// Підраховуємо степінь простого множника i
for num%i == 0 {
e++
num /= i
}
total *= e + 1
}
}
if num > 1 {
// Залишок — простий множник у першому степені
total *= 2
}
return total
}
Сума дільників
Ми можемо скористатися тим самим міркуванням, що й у попередньому розділі.
- Якщо є лише один різний простий дільник , то сума дорівнює:
- Якщо є два різних простих дільники , то ми можемо скласти ту саму таблицю, що й раніше. Єдина відмінність полягає в тому, що тепер ми хочемо обчислити суму, а не підрахувати кількість елементів. Легко бачити, що суму всіх комбінацій можна виразити як:
- У загальному випадку для ми отримуємо формулу:
- C++
- Python
- TypeScript
- Go
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;
}
def sum_of_divisors(num: int) -> int:
total = 1
i = 2
while i * i <= num:
if num % i == 0:
e = 0
# Підраховуємо степінь простого множника i
while num % i == 0:
e += 1
num //= i
# Сума геометричної прогресії 1 + i + i^2 + ... + i^e
s, pw = 0, 1
for _ in range(e + 1):
s += pw
pw *= i
total *= s
i += 1
if num > 1:
# Залишок — простий множник у першому степені: 1 + num
total *= 1 + num
return total
function sumOfDivisors(num: bigint): bigint {
let total = 1n;
for (let i = 2n; i * i <= num; i++) {
if (num % i === 0n) {
let e = 0n;
// Підраховуємо степінь простого множника i
do {
e++;
num /= i;
} while (num % i === 0n);
// Сума геометричної прогресії 1 + i + i^2 + ... + i^e
let sum = 0n,
pow = 1n;
for (let k = 0n; k <= e; k++) {
sum += pow;
pow *= i;
}
total *= sum;
}
}
if (num > 1n) {
// Залишок — простий множник у першому степені: 1 + num
total *= 1n + num;
}
return total;
}
func sumOfDivisors(num int64) int64 {
var total int64 = 1
for i := int64(2); i*i <= num; i++ {
if num%i == 0 {
var e int64 = 0
// Підраховуємо степінь простого множника i
for num%i == 0 {
e++
num /= i
}
// Сума геометричної прогресії 1 + i + i^2 + ... + i^e
var sum, pow int64 = 0, 1
for k := int64(0); k <= e; k++ {
sum += pow
pow *= i
}
total *= sum
}
}
if num > 1 {
// Залишок — простий множник у першому степені: 1 + num
total *= 1 + num
}
return total
}
Мультиплікативні функції
Мультиплікативна функція — це функція , яка задовольняє
якщо і взаємно прості.
І , і є мультиплікативними функціями.
Мультиплікативні функції мають величезне розмаїття цікавих властивостей, які можуть бути дуже корисними у задачах теорії чисел. Наприклад, згортка Діріхле двох мультиплікативних функцій також є мультиплікативною.