ตัวเลขที่มีขนาดใหญ่เกินไปที่จะโพสต์เพื่อให้ที่นี่พวกเขาอยู่บน Pastebin: NUM 1 , NUM 2
จำนวนแรกคือ600^2 = 360000
คนที่ หมายเลขที่สองเหมือนกันยกเว้นการเปลี่ยนแปลงต่อไปนี้:
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
เป็นโมดูโลเดียวกัน16^20
สำหรับทั้งอาร์เรย์ 600 กว้างเริ่มต้นและอาร์เรย์ซิปแล้วเราก็เสร็จแล้ว
ในการทำให้สิ่งต่าง ๆ ง่ายขึ้นเราจะพิจารณาเฉพาะ600^2 = 360000
-digit input number ดังนั้นอาร์เรย์ 600-wide เป็นเพียง 600 x 600 หลัก 10^360000 ~ 2^(2^20.19) < 2^(2^30)
สิ่งนี้ทำให้ง่ายต่อการมองเห็นภาพและมีผลบังคับใช้ตั้งแต่ เพื่อให้สิ่งต่าง ๆ ง่ายขึ้นยิ่งขึ้นเราจะพิจารณาเฉพาะสตริงอินพุตที่มีตารางหลักเป็นสมมาตรตามแนวทแยงมุมหลักเพื่อให้อาร์เรย์ดั้งเดิมและอาร์เรย์ซิปเหมือนกัน สิ่งนี้ยังช่วยให้เราสามารถละเว้นการกลับรายการสตริงเริ่มต้นและการเรียงลำดับดัชนีจากขวาไปซ้ายซึ่งยกเลิกซึ่งกันและกัน
ในการเริ่มต้นเราออกเราสามารถใช้หมายเลขแรกที่จะเป็น360000
คนที่ เพื่อให้ได้ตัวเลขที่สองเราต้องการแก้ไขโดยการเปลี่ยนตัวเลขบางส่วนเพื่อให้ผลรวมเป็นโมดูโลเดียวกัน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
ให้ได้ตัวเลขที่สอง พบว่าทริปเปิลใช้อัลกอริธึมย้อนรอยโลภและสำหรับตัวเลขตัวที่สองเหนือตารางหลักดูเหมือนว่า:
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
สำหรับโบนัสนี่คือพอร์ตแฮชที่ไม่มีประสิทธิภาพใน Python 3 มันไร้ประโยชน์