まず、kをsqrt(n)以上の2の最小の累乗とします。kはまだO(sqrt(n))であるため、複雑さは変わりません。
完全なkxkテーブルを作成するには、一度に1行ずつ作成します。
0行目から始めます。0xorj=jであるため、これは簡単です。
for i in xrange(k):
result[0][i] = i
次に、行をグレイコード順に調べます。グレイコードは、一度に1ビットずつ変更することにより、0から1までのすべての数値をカウントする方法です。2の累乗未満です。
グレイコードプロパティのため、行番号を1ビット変更します。したがって、xorsは1ビットしか変更されないため、古い行から新しい行を簡単に計算できます。
last = 0
for row in graycount(k):
if row == 0: continue
bit_to_change = find_changed_bit(last, row)
for i in xrange(k):
result[row][i] = flip_bit(result[last][i], bit_to_change))
last = row
ここで私たちを助けるためにいくつかの関数が必要です。最初に、異なる最初のビットを見つける関数。
def find_changed_bit(a, b):
i = 1
while True:
if a % 2 != b % 2: return i
i *= 2
a //= 2
b //= 2
O(1)時間で少し変化する関数が必要です。
def flip_bit(a, bit):
thebit = (a // bit) % 2
if thebit:
return a - bit
else:
return a + bit
最後に、注意が必要なのは、グレイコードで数えることです。ウィキペディアから、xor(a、a // 2)を計算することで簡単なグレイコードを取得できることがわかります。
def graycount(a):
for i in xrange(a):
yield slow_xor(a, a // 2)
def slow_xor(a, b):
result = 0
k = 1
while a or b:
result += k * (a % 2 == b % 2)
a //= 2
b //= 2
k *= 2
return result
slow_xorはO(aとbのビット数)ですが、main関数の内部ループでは使用していないため、ここでは問題ありません。