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

Сума дільників (Розбір)

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

σ(n) = 1 + p
1, p, p^2, ..., p^a

Їх сума утворює геометричну прогресію, тому

σ(p^a) = 1 + p + p^2 + p^3 + ... + p^a = \frac{p^{a+1} - 1}{p - 1}

Функція є мультиплікативною, тобто для будь-яких взаємно простих чисел і виконується рівність:

σ(xy) = σ(x) σ(y)

Нехай натуральне число має розклад на прості множники:

n = p_1^{a_1} p_2^{a_2}...p_k^{a_k},

де p_1, p_2, ..., p_k — різні прості числа.

Тоді, використовуючи мультиплікативність і формулу для степенів простих чисел, отримуємо:

σ(n) = σ(p_1^{a_1}) \cdot σ(p_2^{a_2}) \cdot ... \cdot σ(p_k^{a_k}) = \frac{p_1^{a_1+1}-1}{p_1-1} \cdot \frac{p_2^{a_2+1}-1}{p_2-1} \cdot ... \cdot \frac{p_k^{a_k+1}-1}{p_k-1}

Зазначену суму можна записати також у вигляді

\sigma(n) = \prod_{i=1}^{k} \frac{p_i^{a_i+1} - 1}{p_i - 1} = \prod_{i=1}^{k} \left( 1 + p_i + p_i^2 + \dots + p_i^{a_i} \right) = \prod_{i=1}^{k} \sum_{j=0}^{a_i} p_i^{\,j}.

Приклад

Число n = 239 є простим, тобто має рівно два додатних дільники: і . За визначенням функції суми дільників отримуємо:

σ(239) = 1 + 239 = 240

Розгляньмо число n = 24. Його розклад на прості множники має вигляд:

24 = 2^3 \cdot 3

Оскільки числа 2^3 і взаємно прості, можна скористатися мультиплікативністю функції :

σ(24) = σ(2^3) \cdot σ(3) = (1 + 2 + 4 + 8) \cdot (1 + 3) = 15 \cdot 4 = 60.

Обчислимо суму дільників для числа n = 24 безпосередньо. Перелічимо всі додатні дільники числа :

1, 2, 3, 4, 6, 8, 12, 24

Складемо їх:

σ(24) = 1 + 2 + 3 + 4 + 6 + 8 + 12 + 24

Зауважимо, що всі дільники можна згрупувати наступним чином:

σ(24) = \\ 1 + 2 + 3 + 4 + 6 + 8 + 12 + 24 = \\ 1 + 2 + 4 + 8 + 3 \cdot (1 + 2 + 4 + 8) = \\ (1 + 2 + 4 + 8) \cdot (1 + 3) = 15 * 4 = 60

Реалізація алгоритму

Читаємо вхідне значення .

scanf("%lld",&n);

У змінній обчислюємо значення .

res = 1;

У змінній перебираємо всі прості дільники числа (за умовою задачі вони не перевищують ). Для кожного такого дільника за формулою, виведеною в аналізі задачі, обчислюється внесок у суму дільників числа .

for (i = 2; i <= 1000; i++)
{
  p = i;

Нехай — простий дільник числа . Знайдемо найбільшу степінь , для якої i^a ділить .

  while(n % i == 0)
  {
    n /= i; 
    p *= i;
  }

Після завершення циклу отримуємо p = i^{a+1}. Далі множимо поточне значення змінної на \frac{i^{a + 1} - 1}{i - 1}.

  res *= (p - 1) / (i - 1);
}

Виведемо відповідь.

printf("%lld\n",res);

Java реалізація

import java.util.*;

class Main
{
  public static void main(String[] args)
  {
    Scanner con = new Scanner(System.in);
    long n = con.nextLong();
    long res = 1;
    for(int i = 2; i <= 1000; i++)
    {
      long p = i;
      while(n % i == 0)
      {
        n /= i; 
        p *= i;
      }
      res *= (p - 1) / (i - 1);
    }

    System.out.println(res);
    con.close();
  }
}

Python реалізація

Читаємо вхідне значення .

n = int(input())

У змінній обчислюємо значення .

res = 1

У змінній перебираємо всі прості дільники числа (за умовою задачі вони не перевищують ). Для кожного такого дільника за формулою, виведеною в аналізі задачі, обчислюється внесок у суму дільників числа .

for i in range (2,1000) :
  p = i

Нехай — простий дільник числа . Знайдемо найбільшу степінь , для якої i^a ділить .

  while(n % i == 0) :
    n = n // i 
    p *= i

Після завершення циклу отримуємо p = i^{a+1}. Далі множимо поточне значення змінної на \frac{i^{a + 1} - 1}{i - 1}.

  res *= (p - 1) // (i - 1) 

Виведемо відповідь.

print(res)