Оскільки потрібно факторизувати багато чисел, що не перевищують 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);