Розклад на множники#11611

Оскільки потрібно факторизувати багато чисел, що не перевищують 10^7, вигідно виконати попереднє обчислення. За допомогою модифікованого решета Ератосфена побудуємо масив (smallest prime factor), де

Факторизація числа виконується наступним чином. Поки n > 1, беремо p = spf[n], найменший простий дільник поточного значення , і ділимо на , поки ділення виконується націло, підраховуючи показник степеня. Потім виводимо множник у відповідному степені та переходимо до наступного простого дільника. Прості множники при цьому отримуються у порядку зростання, що відповідає необхідному формату виведення.

Побудова решета вимагає O(n~log~log~n) часу. Кожне ділення зменшує щонайменше удвічі, тому факторизація одного числа виконується за O(log~n). Загальна часова складність для запитів становить O(n~log~log~n + q~log~n).

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

Оголосимо масив , у якому містить найменший простий дільник числа .

#define MAX 10000001
int spf[MAX + 1];

Функція Sieve реалізує решето Ератосфена та заповнює масив .

void Sieve(int n)
{
  for (int i = 0; i < n; i++)
    spf[i] = i;
  for (int i = 2; i <= sqrt(n); i++)
    if (spf[i] == i)
      for (int j = i * i; j < n; j += i)
        if (spf[j] == j) spf[j] = i;
}

Функція factorize розкладає число на прості множники, використовуючи масив .

void factorize(int n)
{

Виділяємо прості множники з числа , поки воно більше .

  while (n > 1)
  {

Найменший простий дільник числа дорівнює .

    int p = spf[n];

Знаходимо максимальний степінь , для якого p^{power} ділить число .

    int power = 0;
    while (n % p == 0)
    {
      n /= p;
      power++;
    }

Виводимо множник p^{power}.

    if (power > 1) printf("%d^%d", p, power); else printf("%d", p);

Між множниками слід виводити знак ''.

    if (n > 1) printf("*");
  }
  printf("\n");
}

Основна частина програми. Заповнюємо масив , використовуючи решето Ератосфена.

Sieve(MAX);

Для кожного вхідного значення виводимо його розклад на прості множники.

while (scanf("%d", &n) == 1)
  factorize(n);