以下で説明するタスクが理論的に可能かどうか、可能であればどうすればそれができるかを知りたいです。
要素の空間 (つまり、と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 暗号化キーは、 上の 1 つの順列を指定しN=256^16
ます。その順列は、太陽系の原子よりも多くのメンバーを持っているため、コンピューターに完全に保存できませんでした. ただし、アイテムへのアクセスは許可されます。AES を使用してデータを暗号化することにより、データをブロックごとに調べ、ブロック ( のメンバーrange(N)
) ごとに暗号化されたブロックを出力します。そのメンバーはrange(N)
、順列の元のブロックのインデックス番号にあります。復号化するときは、逆のことを行っています (ブロックのインデックス番号を見つける) O(1)
。
AES やその他のブロック暗号を使用する際の問題は、非常に具体的N
なN
.S[i]
私が好きな順列。
サイズと順列番号O(1)
を指定して、順列でアイテム アクセスを取得することは可能ですか? もしそうなら、どのように?N
i
(幸運にもここでコードの回答を得ることができれば、それらが Python で提供されることを感謝します。)
更新:
一部の人々は、置換数自体が非常に巨大であり、数を読み取るだけではタスクが実行不可能になるという悲しい事実を指摘しました。次に、私の質問を修正したいと思います:順列の辞書式番号の階乗表現へのアクセスが与えられた場合、O(できるだけ小さい)で順列の任意のアイテムを取得することは可能ですか?