Я хочу знать, теоретически возможно ли объяснение, описанное ниже, и если да, то как я могу это сделать.
Вам предоставляется пространство элементов N
(т.е. все числа между 0
и N-1
.). Посмотрите на пространство всех перестановок в этом пространстве и назовите его S
. i
-й член S
, который может быть помечен S[i]
, является перестановкой с лексикографическим номером i
.
Например, если N
равно 3, то S
- это список перестановок:
S[0]: 0, 1, 2
S[1]: 0, 2, 1
S[2]: 1, 0, 2
S[3]: 1, 2, 0
S[4]: 2, 0, 1
S[5]: 2, 1, 0
(Конечно, при просмотре большого N
это пространство становится очень большим, N!
, если быть точным.)
Теперь я уже знаю как получить перестановку по его номеру индекса i
, и я уже знаю, как сделать обратное (получить лексикографическое число данной перестановки. ) Но я хочу что-то лучше.
Некоторые перестановки могут быть огромными сами по себе. Например, если вы смотрите на N=10^20
. (Размер S
будет (10^20)!
, который, я считаю, является самым большим числом, которое я когда-либо упоминал в вопросе:)
Если вы посмотрите на случайную перестановку в этом пространстве, это будет настолько большим, что вы не сможете сохранить все это на своем жестком диске, не говоря уже о вычислении каждого из элементов по лексикографическому номеру. Я хочу, чтобы иметь возможность доступа к элементам на этой перестановке, а также получить индекс каждого элемента. То есть, заданные N
и i
для указания перестановки, имеют одну функцию, которая принимает номер индекса и находит номер, который находится в этом индексе, и другую функцию, которая принимает число и находит, в каком индексе он находится. Я хочу сделать это в O(1)
, поэтому мне не нужно сохранять или перебирать каждый элемент в перестановке.
Сумасшедший, вы говорите? Невозможно? Это может быть. Но учтите это: блочный шифр, такой как AES, по сути является перестановкой, и он почти выполняет задачи, описанные выше. AES имеет размер блока 16 байт, что означает, что N
есть 256^16
, который находится вокруг 10^38
. (Размер S
, а не то, что он имеет значение, представляет собой ошеломляющий (256^16)!
или около 10^85070591730234615865843651857942052838
, который превосходит мою недавнюю запись для "наибольшего числа, упомянутого в переполнении стека":)
Каждый ключ шифрования AES указывает одну перестановку на N=256^16
. Эта перестановка не может быть сохранена целиком на вашем компьютере, потому что в ней больше членов, чем в солнечной системе. Но он позволяет вам доступ к элементам. Зашифровывая данные с помощью AES, вы смотрите блок данных по блоку, а для каждого блока (член range(N)
) вы выводите зашифрованный блок, член которого range(N)
, который находится в индексе номера оригинала блок в перестановке. И когда вы расшифровываете, вы делаете обратное (нахождение номера индекса блока.) Я считаю, что это сделано в O(1)
, я не уверен, но в любом случае это очень быстро.
Проблема с использованием AES или любого другого блочного шифрования заключается в том, что он ограничивает вас очень специфическим N
, и он, вероятно, только фиксирует небольшую часть возможных перестановок, в то время как я хочу иметь возможность использовать любой N
Мне нравится, и я делаю доступ к элементам любой перестановки S[i]
, которая мне нравится.
Можно ли получить доступ к элементу O(1)
при перестановке, заданный размер N
и номер перестановки i
? Если да, то как?
(Если мне посчастливилось получить ответы на код здесь, я был бы признателен, если они будут на Python.)
UPDATE
Некоторые люди отметили печальный факт, что само перестановочное число будет настолько огромным, что просто чтение номера сделает задачу невыполнимой. Затем я хотел бы пересмотреть свой вопрос: Учитывая доступ к факадическому представлению лексикографического числа перестановок, можно ли получить любой элемент в перестановке в O (как можно меньше)?