Flag - printer
import galois
import numpy as np
MOD = 7514777789
points = []
for line in open('encoded.txt', 'r').read().strip().split('\n'):
x, y = line.split(' ')
points.append((int(x), int(y)))
GF = galois.GF(MOD)
matrix = []
solution = []
for point in points:
x, y = point
solution.append(GF(y % MOD))
row = []
for i in range(len(points)):
row.append(GF((x ** i) % MOD))
matrix.append(GF(row))
open('output.bmp', 'wb').write(bytearray(np.linalg.solve(GF(matrix), GF(solution)).tolist()[:-1]))
Solution
Ta thấy rằng file encoded.txt bao gồm tập hợp các điểm với nằm từ 0 —> 1769610 và giá trị y random. Và code mẫu đề bài cho là thực hiện giải ma trận dưới đây, tuy nhiên nó chạy rất chậm và độ phức tạp là
Sau một lúc osint thì ta nhận thấy rằng đây là ma trận Vandermonde và nó liên quan đến Larange interpolation (nội suy larange). Và ta có được công thức:
Cùng với đó ta cũng tìm thấy được một blog: https://codeforces.com/blog/entry/94143
Đầu tiên ta sẽ giảm độ phức tạp của việc tính
Thay vì với mỗi vòng lặp ta sẽ chạy lại để tính thì ta có thể làm như sau:
=
Ở đây to có thể nhân hết vào và chia đi . Điều tuyệt vời là ta có thể sử dụng lim để xử lý việc
Thế nên việc của ta là chỉ cần tìm với rồi thế từng vô.
Tiếp theo ta sẽ đến giảm độ phức tạp của việc nhân nhiều đa thức
Ta biết rằng nhân đa thức trong sage có
Giả sử có m đa thức thì nếu nhân từ từ từng đa thức lại với nhau ta sẽ mất

Còn nếu ta sử dụng chia để trị để nhân đa thức thì ta sẽ mất

Giờ việc cuối cùng của ta là là thiết lập công thức
Đặt
—>
với:
Code dưới đây đã mất tầm 6 - 7 tiếng để chạy và mình đã để chạy qua đêm để ra FLAG. (huhu)
from tqdm import tqdm
MOD = 7514777789
points = []
for line in open('encoded.txt', 'r').read().strip().split('\n'):
x, y = line.split(' ')
points.append((int(x), int(y)))
F = GF(MOD)
R.<x> = F['x']
def multiply_poly_list(poly_list):
if len(poly_list) == 1:
return poly_list[0]
n = len(poly_list) // 2
return multiply_poly_list(poly_list[:n]) * multiply_poly_list(poly_list[n:])
P = multiply_poly_list([x - i for i in range(len(points))])
d_P = derivative(P)
def calc_poly(points, start_index, bar):
bar.update(int(1))
n = len(points)
if n == 1:
x_i = points[0][0]
y_i = points[0][1]
v = y_i / d_P(x_i)
return v
f0 = calc_poly(points[:n//2], start_index, bar)
f1 = calc_poly(points[n//2:], start_index + n//2, bar)
p0 = multiply_poly_list([x - (i + start_index) for i in range(n//2)])
p1 = multiply_poly_list([x - (i + start_index) for i in range(n//2, n)])
return f0 * p1 + f1 * p0
n = 2 * len(points) - 1
bar = tqdm(total=int(n))
poly = calc_poly(points, 0, bar)
coeffs = poly.numerator().list()
with open('out.txt', 'w') as f:
f.write('\n'.join([str(i) for i in coeffs]))
print("Finished")
listarr = [int(_) for _ in open("out.txt", "r").read().strip().split('\n')]
print(listarr)
open('output.bmp', 'wb').write(bytearray(listarr[:-1]))

