import fractions as f
K = 2 ** 50
N = 50
cnt = 4
mod_ = [995662561, 995662609, 995662621, 998244353]
base_ = [31, 31, 31, 31]
y = []
for i in range(N):
y.append([])
for j in range(N):
if i == j:
y[i].append(f.Fraction(1, 1))
else:
y[i].append(f.Fraction(0, 1))
for j in range(cnt):
y[i].append(f.Fraction(pow(base_[j], N - i, mod_[j]) * K, 1))
def dot(x, y):
n = len(x)
ans = 0
for i in range(n):
ans += x[i] * y[i]
return ans
delta = f.Fraction(99, 100)
n, m = N, N + cnt
y_star = [[y[0][i] for i in range(m)]]
mu = [[f.Fraction(0, 1) for i in range(m)] for j in range(n)]
for i in range(1, n):
print('Gram-Schmidt: i =', i)
y_star.append([y[i][j] for j in range(m)])
for j in range(i):
mu[i][j] = dot(y_star[j], y_star[i]) / dot(y_star[j], y_star[j])
for k in range(m):
y_star[i][k] -= y_star[j][k] * mu[i][j]
gamma = [dot(y_star[i], y_star[i]) for i in range(n)]
def round(x):
return (x + f.Fraction(1, 2)).__floor__()
def reduce(k, l):
if abs(mu[k][l]) > f.Fraction(1, 2):
for i in range(m):
y[k][i] -= round(mu[k][l]) * y[l][i]
for j in range(l):
mu[k][j] -= round(mu[k][l]) * mu[l][j]
mu[k][l] -= round(mu[k][l])
def exchange(k):
y[k - 1], y[k] = y[k], y[k - 1]
nu = mu[k][k - 1]
delta = gamma[k] + nu * nu * gamma[k - 1]
mu[k][k - 1] = nu * gamma[k - 1] / delta
gamma[k] *= gamma[k - 1] / delta
gamma[k - 1] = delta
for j in range(k - 1):
mu[k - 1][j], mu[k][j] = mu[k][j], mu[k - 1][j]
for i in range(k + 1, n):
xi = mu[i][k]
mu[i][k] = mu[i][k - 1] - nu * mu[i][k]
mu[i][k - 1] = mu[k][k - 1] * mu[i][k] + xi
k = 1
maxk = 1
while k < n:
if maxk < k:
maxk = k
print('LLL: new k =', k)
reduce(k, k - 1)
if gamma[k] >= (delta - mu[k][k - 1] ** 2) * gamma[k - 1]:
for l in range(k - 2, -1, -1):
reduce(k, l)
k = k + 1
else:
exchange(k)
if k > 1:
k = k - 1
print(y[0])
s1 = s2 = ''
for i in range(n):
now = int(y[0][i])
if now <= 0:
s1 += 'a'
s2 += chr(ord('a') - now)
else:
s1 += chr(ord('a') + now)
s2 += 'a'
print(s1)
print(s2)
def calc_hash(s, b, m):
ans = 0
for i in range(len(s)):
ans = (ans + (ord(s[i]) - ord('a')) * pow(b, N - i, m)) % m
return ans
for i in range(cnt):
print(calc_hash(s1, base_[i], mod_[i]), calc_hash(s2, base_[i], mod_[i]))
\sum_{i=1}^nx_ib^{i-1}-\sum_{i=1}^nx_ib^{2n-i+1}\equiv0\pmod p\sum_{i=1}^nx_i(b^{i-1}-b^{2n-i+1})\equiv0\pmod p
参考代码:
import fractions as f
K = 2 ** 200
N = 50
cnt = 1
mod_ = [2305843009213693951]
base_ = [1145141919]
y = []
for i in range(N):
y.append([])
for j in range(N):
if i == j:
y[i].append(f.Fraction(1, 1))
else:
y[i].append(f.Fraction(0, 1))
for j in range(cnt):
#y[i].append(f.Fraction(pow(base_[j], N - i, mod_[j]) * K, 1))
y[i].append(f.Fraction((pow(base_[j], 2 * N - i - 1, mod_[j]) - pow(base_[j], i, mod_[j])) % mod_[j] * K, 1))
def dot(x, y):
n = len(x)
ans = 0
for i in range(n):
ans += x[i] * y[i]
return ans
delta = f.Fraction(99, 100)
n, m = N, N + cnt
y_star = [[y[0][i] for i in range(m)]]
mu = [[f.Fraction(0, 1) for i in range(m)] for j in range(n)]
for i in range(1, n):
print('Gram-Schmidt: i =', i)
y_star.append([y[i][j] for j in range(m)])
for j in range(i):
mu[i][j] = dot(y_star[j], y_star[i]) / dot(y_star[j], y_star[j])
for k in range(m):
y_star[i][k] -= y_star[j][k] * mu[i][j]
gamma = [dot(y_star[i], y_star[i]) for i in range(n)]
def round(x):
return (x + f.Fraction(1, 2)).__floor__()
def reduce(k, l):
if abs(mu[k][l]) > f.Fraction(1, 2):
for i in range(m):
y[k][i] -= round(mu[k][l]) * y[l][i]
for j in range(l):
mu[k][j] -= round(mu[k][l]) * mu[l][j]
mu[k][l] -= round(mu[k][l])
def exchange(k):
y[k - 1], y[k] = y[k], y[k - 1]
nu = mu[k][k - 1]
delta = gamma[k] + nu * nu * gamma[k - 1]
mu[k][k - 1] = nu * gamma[k - 1] / delta
gamma[k] *= gamma[k - 1] / delta
gamma[k - 1] = delta
for j in range(k - 1):
mu[k - 1][j], mu[k][j] = mu[k][j], mu[k - 1][j]
for i in range(k + 1, n):
xi = mu[i][k]
mu[i][k] = mu[i][k - 1] - nu * mu[i][k]
mu[i][k - 1] = mu[k][k - 1] * mu[i][k] + xi
k = 1
maxk = 1
while k < n:
if maxk < k:
maxk = k
print('LLL: new k =', k)
reduce(k, k - 1)
if gamma[k] >= (delta - mu[k][k - 1] ** 2) * gamma[k - 1]:
for l in range(k - 2, -1, -1):
reduce(k, l)
k = k + 1
else:
exchange(k)
if k > 1:
k = k - 1
print(y[0])
s1 = s2 = ''
for i in range(n):
now = int(y[0][i])
if now <= 0:
s1 += 'a'
s2 += chr(ord('a') - now)
else:
s1 += chr(ord('a') + now)
s2 += 'a'
print(s1)
print(s2)
print(s1 + s2[::-1])
def calc_hash(s, b, m):
ans = 0
for i in range(len(s)):
ans = (ans + (ord(s[i]) - ord('a')) * pow(b, i, m)) % m
return ans
s = s1 + s2[::-1]
#for i in range(cnt):
# print(calc_hash(s1, base_[i], mod_[i]), calc_hash(s2, base_[i], mod_[i]))
for i in range(cnt):
print(calc_hash(s, base_[i], mod_[i]), calc_hash(s[::-1], base_[i], mod_[i]))