Нехай — задана перестановка, а — елемент перестановки, який знаходиться на позиції . Розглянемо послідовність елементів: i, p[i], p[p[i]], .... Оскільки кількість елементів у перестановці кінцева, існує таке мінімальне , що p[i]^k = i. Послідовність елементів i, p[i], p[p[i]], ..., p[i]^{k-1}, для якої p[i]^k = i, будемо називати циклом. Довжина циклу дорівнює .
Будь-яку перестановку можна подати у вигляді списку циклів. Наприклад, перестановка [4, 3, 2, 5, 1, 6] представляється як (1, 4, 5)(2, 3)(6).
Наприклад, послідовність (1, p[1], p[p[1]]) = (1, 4, 5) утворює цикл, оскільки p[p[p[1]]] = p[1]^3 = 1. Довжина цього циклу дорівнює .
Ступінь перестановки дорівнює НСК довжин її циклів.
Приклад
У першому прикладі перестановка [4, 3, 2, 5, 1, 6] представляється у вигляді (1, 4, 5)(2, 3)(6). Довжини циклів дорівнюють і . Ступінь перестановки дорівнює НСК(3, 2, 1) = 6.
У другому прикладі перестановка [4, 3, 6, 8, 9, 7, 2, 1, 5] представляється у вигляді (1, 4, 8)(2, 3, 6, 7)(5, 9). Довжини циклів дорівнюють і . Ступінь перестановки дорівнює НСК(3, 4, 2) = 12.
Реалізація алгоритму
Масив зберігає вхідну перестановку. Масив використовується для позначення оброблених елементів.
#define MAX 101
int p[MAX], used[MAX];Читаємо вхідну перестановку.
scanf("%d",&n);
for(i = 1; i <= n; i++)
scanf("%d",&p[i]);У змінній підраховуємо ступінь перестановки .
res = 1;
memset(used, 0, sizeof(used));Перебираємо індекси перестановки. Для кожного обробленого індексу встановлюємо used[i] = 1.
for (i = 1; i <= n; i++)
if (!used[i])
{Цикл з елементом ще не знайдено. Шукаємо довжину циклу у перестановці, починаючи з індексу j = i. Для цього послідовно переходимо по індексах j, p[j], p[p[j]], ..., доки не зустрінеться вже пройдений елемент. Усі пройдені індекси позначаємо як відвідані, встановлюючи used[j] = 1.
len = 0;
j = i;
while (!used[j])
{
used[j] = 1;
j = p[j];
len++;
}Змінна містить довжину поточного знайденого циклу. Обчислюємо НСК довжин всіх циклів.
res = lcm(res, len);
}Виводимо відповідь.
printf("%d\n", res);