2n
長さn
が約の 2 進数を考えるとしましょう1000
。次のプロパティを持つkth
数値 (k は によって制限されます) を探しています。10^9
- の金額は、次のように記述できる
1's
金額と同じです。0's
#(1) = #(0)
- この番号のすべてのプレフィックスには、
0's
少なくとも1's
. 次の文を否定した後の方が理解しやすいかもしれませ1's
ん0's
。
そして、基本的にはそれだけです。明確にするために、いくつかの例
n=2
をk=2
見てみましょう2n
:
0000
0001
0010
0011
0100
0101
0110
0111
1000
and so on...
そして、2nd
これら 2 つの要件を満たす数を見つけなければなりません。つまり0011
、 が最初のもので、0101
が 2 番目のものです。を変更するk=3
と、反対のビットの量が同じ数があるため、答えは存在しませんが、 の場合、0110
接頭辞があるため、数値は 2 番目の制約を満たさず、最上位ビット011
がすべての数値と同じになります。1
では、アルゴリズムを見つけるためにこれまでに何をしたのでしょうか。
私の最初のアイデアは、可能なすべてのビット設定を生成し、それらの 2 つのプロパティがあるかどうかを確認することでしたが、それらをすべて生成するとO(2^(2n))
、n=1000
.
0011
さらに、 for n=2
、000111
forなどよりも小さいすべての数値をチェックする必要がないことを認識していn=3
ます...率直に言って、最上位ビットの半分が「そのまま」残っているものは、これらの数値が#(1) = #(0)
条件を満たす可能性がないためです。それを使えばn
半分に減らせますが、あまり役に立ちません。2 * forever の代わりに、アルゴリズムを永久に実行しています。それはまだO(2^n)
複雑で、大きすぎます。
アルゴリズムのアイデアはありますか?
結論
このテキストは、Andy Jones の投稿を読んだ後の私の考えの結果として作成されました。
まず第一に、Andy の投稿Kasa 2009の次のドキュメントのポイント 6 であるため、使用したコードは投稿しません。あなたがしなければならないのはnr
、私が説明したことをそれと見なすことだけk
です。Dyck words アルゴリズムのランクを解除すると、答えをより迅速に見つけることができます。ただし、1 つのボトルネックがあります。
while (k >= C(n-i,j))
それを考慮するとn <= 1000
、カタロニア語の数は非常に巨大になる可能性がありC(999,999)
ます。いくつかの大きな数の演算を使用できますが、一方で、それを超えて標準の整数を使用するためのちょっとしたトリックを思い付きました。
よりも大きい限り、カタロニア語の数が実際にどのくらい大きいかを知りたくありませんk
。そこで、部分和をn x n
テーブルにキャッシュするカタロニア語の数字を作成します。
... ...
5 | 42 ...
4 | 14 42 ...
3 | 5 14 28 ...
2 | 2 5 9 14 ...
1 | 1 2 3 4 5 ...
0 | 1 1 1 1 1 1 ...
---------------------------------- ...
0 1 2 3 4 5 ...
それを生成するのは非常に簡単です:
C(x,0) = 1
C(x,y) = C(x,y-1) + C(x-1,y) where y > 0 && y < x
C(x,y) = C(x,y-1) where x == y
したがって、これだけを見ることができます:
C(x,y) = C(x,y-1) + C(x-1,y) where y > 0 && y < x
オーバーフローを引き起こす可能性があります。
この時点で停止し、定義を提供しましょう。
k-flow
- 整数の実際のオーバーフローではなく、 の値C(x,y)
が より大きいという情報ですk
。
私の考えは、上記の式を実行するたびに がC(x,y)
よりも大きいk
か、合計コンポーネントのいずれかが であるかどうかを確認することです-1
。-1
マーカーとして機能する代わりに配置した場合、それk-flow
は起こりました。k-flow
数値が任意の正の数値で合計される場合k-flowed
、特に 2 つのk-flowed
数値の合計が であることは明らかだと思いk-flowed
ます。
最後に証明しなければならないことは、実際のオーバーフローが発生する可能性がないことです。a + b
実際のオーバーフローは、それらのどれではないかを合計した場合にのみ発生する可能性がありますk-flowed
が、合計すると、実際のオーバーフローが発生しました。
もちろん、最大値はa + b <= 2 * k <= 2*10^9 <= 2,147,483,647
、この不等式の最後の値が符号付きの int の値であると記述できるため、不可能です。また、私の場合のように、int は 32 ビットであると仮定します。