Получение объекта по номеру — различия между версиями
Строка 1: | Строка 1: | ||
== Общий алгоритм получения комбинаторного объекта по номеру в лексикографическом порядке == | == Общий алгоритм получения комбинаторного объекта по номеру в лексикографическом порядке == | ||
− | :Получим элементы объекта по порядку, сначала определим какой элемент будет стоять на 1-м месте, 2-м и т.д. | + | : Получим элементы объекта по порядку, сначала определим какой элемент будет стоять на 1-м месте, 2-м и т.д. Пусть мы нашли первые i элементов нашего объекта. Для всех вариантов i+1 элемента посчитаем диапазон номеров объектов с данным префиксом. Если искомый номер входит в один из диапазонов, то очевидно мы нашли элемент, который должени стоять на (i+1)-ом месте. |
− | Пусть мы нашли первые i элементов нашего объекта. Для всех вариантов i+1 элемента посчитаем диапазон номеров объектов с данным префиксом. Если искомый номер входит в один из диапазонов, то очевидно мы нашли элемент, который должени стоять на (i+1)-ом месте. | + | ''//В начале каждого шага numOfObject {{---}} номер комбинаторного объекта среди объектов с заданным префиксом. '' |
− | ''//В начале каждого шага numOfObject - | + | '''for''' i = 1 '''to''' n '''do''' ''//n {{---}} количество элементов в комбинаторном объекте'' |
− | '''for''' i = 1 '''to''' n '''do''' ''//n - количество элементов в комбинаторном объекте'' | ||
'''for''' j = 1 '''to''' n '''do''' ''//перебираем елементы в лексикографическом порядке'' | '''for''' j = 1 '''to''' n '''do''' ''//перебираем елементы в лексикографическом порядке'' | ||
'''if''' можем поставить на i-e место | '''if''' можем поставить на i-e место | ||
Строка 19: | Строка 18: | ||
== Перестановки == | == Перестановки == | ||
Рассмотрим алгоритм получения i-ой в лексикографическом порядке перестановки размера n. | Рассмотрим алгоритм получения i-ой в лексикографическом порядке перестановки размера n. | ||
− | <tex>P_{n} </tex> ''- количество перестановок размера n | + | <tex>P_{n} </tex> ''{{---}} количество перестановок размера n |
− | permutation[n] ''- искомая перестановка'' | + | permutation[n] ''{{---}} искомая перестановка'' |
was[n] ''- использовали ли мы уже эту цифру в перестановке'' | was[n] ''- использовали ли мы уже эту цифру в перестановке'' | ||
'''for''' i = 1 '''to''' n '''do''' ''//n - количество цифр в перестановке'' | '''for''' i = 1 '''to''' n '''do''' ''//n - количество цифр в перестановке'' | ||
Строка 39: | Строка 38: | ||
== Сочетания == | == Сочетания == | ||
Рассмотрим алгоритм получения i-го в лексикографическом порядке размещения <tex> A^k_n </tex> | Рассмотрим алгоритм получения i-го в лексикографическом порядке размещения <tex> A^k_n </tex> | ||
− | <tex>A^{k}_{n} </tex> ''- количество размещений из n по k | + | <tex>A^{k}_{n} </tex> ''{{---}} количество размещений из n по k |
− | placement[n] ''- искомое размещение'' | + | placement[n] ''{{---}} искомое размещение'' |
− | was[n] ''- использовали ли мы уже эту цифру в размещении'' | + | was[n] ''{{---}} использовали ли мы уже эту цифру в размещении'' |
'''for''' i = 1 '''to''' k '''do''' ''//k - количество цифр в размещении'' | '''for''' i = 1 '''to''' k '''do''' ''//k - количество цифр в размещении'' | ||
alreadyWas = (numOfPlacement-1) div <tex> A^{k-i}_{n-i} </tex> ''// сколько цифр уже полностью заняты размещениями с меньшим номером'' | alreadyWas = (numOfPlacement-1) div <tex> A^{k-i}_{n-i} </tex> ''// сколько цифр уже полностью заняты размещениями с меньшим номером'' |
Версия 03:55, 29 октября 2011
Содержание
Общий алгоритм получения комбинаторного объекта по номеру в лексикографическом порядке
- Получим элементы объекта по порядку, сначала определим какой элемент будет стоять на 1-м месте, 2-м и т.д. Пусть мы нашли первые i элементов нашего объекта. Для всех вариантов i+1 элемента посчитаем диапазон номеров объектов с данным префиксом. Если искомый номер входит в один из диапазонов, то очевидно мы нашли элемент, который должени стоять на (i+1)-ом месте.
//В начале каждого шага numOfObject — номер комбинаторного объекта среди объектов с заданным префиксом. for i = 1 to n do //n — количество элементов в комбинаторном объекте for j = 1 to n do //перебираем елементы в лексикографическом порядке if можем поставить на i-e место then if numOfObject > (количество комбинаторных обектов с данным префиксом) then numOfObject -= (количество комбинаторных обектов с данным префиксом) else then ans[i]=j //поставим на i-e место текущий элемент, т.к. еще не все объекты с этим префиксом - меньше перейти к выбору следующего элемента
- Несложно понять, что корректность алгоритма следует из его построения.
- Сложность алгоритма , где - сложность вычисления количества комбинаторных объектов с
данным префиксом.
Перестановки
Рассмотрим алгоритм получения i-ой в лексикографическом порядке перестановки размера n.
— количество перестановок размера n permutation[n] — искомая перестановка was[n] - использовали ли мы уже эту цифру в перестановке for i = 1 to n do //n - количество цифр в перестановке alreadyWas = (numOfPermutation-1) div // сколько цифр уже полностью заняты перестановками с меньшим номером numOfPermutation = ((numOfPermutation-1) mod ) + 1 //сейчас мы должны поставить ту цифру, которая еще полностью не занята, т.е. alreadyWas+1, которая еще не занята for j = 1 to n do if was[j] = false then cntFree++ if cntFree = alreadyWas+1 then ans[i] = j was[j] = true
Данный алгоритм работает за
. Мы можем посчитать за . Асимптотику можно улучшить до , если использовать структуры данных, которые позволяют искать i-ый элемент множества и удалять элемент множества за . Например декартово дерево по неявному ключу.Сочетания
Рассмотрим алгоритм получения i-го в лексикографическом порядке размещения
— количество размещений из n по k placement[n] — искомое размещение was[n] — использовали ли мы уже эту цифру в размещении for i = 1 to k do //k - количество цифр в размещении alreadyWas = (numOfPlacement-1) div // сколько цифр уже полностью заняты размещениями с меньшим номером numOfPlacement = ((numOfPlacement-1) mod ) + 1 //сейчас мы должны поставить ту цифру, которая еще полностью не занята, т.е. alreadyWas+1, которая еще не занята for j = 1 to n do if was[j] = false then cntFree++ if cntFree = alreadyWas+1 then ans[i] = j was[j] = true
Сложность алгоритма
.