数字は大きすぎて投稿できないため、ここではPastebinにあります:num 1、num 2。
最初の数字は 600^2 = 360000
1です。2番目の番号は、次の変更を除いて同じです。
Positions to change to "2": 605, 1811, 3001, 6603
Positions to change to "4": 1805, 3003, 57348, 208895
Positions to change to "5": 602, 1201, 2405, 3004
Positions to change to "6": 1203, 1802
Positions to change to "7": 12, 609, 5401, 7200
Positions to change to "8": 1, 2, 4, 6, 600, 1200, 1808, 2400, 3600, 4803
両方ともハッシュし271088937720654725553339294593617693056
ます。
説明
コードの前半を見てみましょう。
lW% e# Read input number as string, and reverse
600/ e# Split every 600 digits, forming a 2D array
_z e# Duplicate and zip, swapping rows and columns
{ }% e# For both arrays...
JfbDb e# Find sum of S[i][j]*13^i*19^j, where S are the character values
e# and the indices are from right to left, starting at 0.
GK# e# Take modulo 16^20
... ... e# (Rest of code irrelevant)
したがって、合計S[i][j]*13^i*19^j
が同じモジュロになるように2つの入力数を見つけることができる場合16^20
、最初の600ワイド配列とzip配列の両方に完了です。
物事をもう少し簡単にする600^2 = 360000
ために、600桁の配列がちょうど600 x 600の数字になるように、1 桁の入力番号のみを考慮します。これにより、物事を視覚化するのが簡単になります10^360000 ~ 2^(2^20.19) < 2^(2^30)
。さらに簡素化するために、元の配列と圧縮された配列が同じになるように、数字の正方形が主対角線に沿って対称であるような入力文字列のみを考慮します。これにより、最初の文字列の反転と、互いに相殺される右から左へのインデックス番号付けを無視することもできます。
まず、最初の数字を1にすることができ360000
ます。2番目の数字を取得するには、数字の一部を変更して、合計がmodulo 16^20
になるように変更し、数字の正方形の対称性を維持します。トリプルのリストを見つけることでこれを達成します(i, j, k)
ので、
sum of k*(13^i 19^j + 19^i 13^j) == 0 mod 16^20
ここで1 <= k <= 8
、桁1を増やす量(つまり、桁を2から9に変更する-0を含めることはできましたが、必要ありませんでした)0 <= i < j < 600
はインデックスペアです。
私たちが持っていたら(i, j, k)
トリプレットを、我々はで数字を変更(i, j)
して(j, i)
の1+k
秒数を取得します。トリプレットは、貪欲なバックトラッキングアルゴリズムを使用して検出され、数字の上の2番目の数字は次のようになります。
188181811111711 ...
815112111711111 ...
851611111111111 ...
116114118112111 ...
811115111111111 ...
121451111111111 ...
811111111111111 ...
111111111111111 ...
111811111111111 ...
171111111111111 ...
111111111111111 ...
111211111111111 ...
711111111111111 ...
111111111111111 ...
111111111111111 ...
............... .
............... .
............... .
たとえば(i, j, k) = (0, 1, 7)
、数字(0, 1)
(位置600*0 + 1 = 1
)および(1, 0)
(位置600*1 + 0 = 600
)をに変更することに対応し1 + 7 = 8
ます。
Python 3のバックトラッカーは次のとおりです。ただし、実際にバックトラッキングが行われなかったため、詳細な調査により幸運だったことがわかりました。
n = 16**20
L = [(k *(pow(13,i,n)*pow(19,j,n) + pow(19,i,n)*pow(13,j,n)) % n, i, j, k)
for i in range(600) for j in range(600) for k in range(1, 9) if i < j]
L.sort(reverse=True)
stack = [(n, 0, [])]
while stack:
k, index, result = stack.pop()
if k == 0:
print(result)
break
if index == len(L):
continue
stack.append((k, index+1, result)) # Don't include triplet
if L[index][0] <= k:
stack.append((k - L[index][0], index+1, result + [L[index][1:]])) # Include
ボーナスのために、ここにあるハッシュのそれほど効率的でないポートは、それが役に立たなかった3 Pythonで。