# n+1 primality prover
def gcd(a, b):
while b <> 0:
a, b = b, a % b
return a
def signum(n):
if n > 0: return 1
if n < 0: return -1
return 0
def jacobi(a, p):
a, t = a % p, 1
while a <> 0:
while a % 2 == 0:
a /= 2
if p % 8 in (3, 5): t *= -1
a, p = p, a
if a % 4 == 3 and p % 4 == 3: t *= -1
a %= p
return t if p == 1 else 0
def u(p, q, m, n):
# nth element of Lucas U(p,q) sequence mod m
# for the bits of n from right to left:
# u2, v2, and q2 double at each bit and are added
# to the accumulators u, v, and q at each 1-bit
d, u2, v2, q2 = p*p - 4*q, 1, p, q
if n%2==1: u,v,q = 1,p,q
else: u,v,q = 0,2,1
while n > 1:
u2, v2, q2, n = \
(u2*v2)%m, (v2*v2-2*q2)%m, (q2*q2)%m, n//2
if n%2 == 1:
u, v = u*v2+u2*v, v*v2+d*u*u2
u = (u/2)%m if u%2==0 else ((u+m)/2)%m
v = (v/2)%m if v%2==0 else ((v+m)/2)%m
q *= q2
return u
def provePrime(n):
f, fs, fp, r, d = 2, [], 1, n+1, 5
while fp*fp < n:
if f*f > r:
fs.append(r)
break
while r % f == 0:
r /= f; fp *= f
if f not in fs:
fs.append(f)
f += 1
while jacobi(d, n) <> -1:
d = (abs(d)+2) * signum(d) * -1
p, q = 1, (1-d)/4
if gcd(d, n) > 1: return False
if u(p, q, n, n+1) <> 0: return False
for x in fs:
while True:
if gcd(u(p,q,n,(n+1)/x), n) == 1:
print d, p, q, x, u(p, q, n, (n+1)/x)
break
p, q = p + 2, p + q + 1
return True
print provePrime(10**12+39)
print provePrime(10**12+61)
IyBuKzEgcHJpbWFsaXR5IHByb3ZlcgoKZGVmIGdjZChhLCBiKToKICAgIHdoaWxlIGIgPD4gMDoKICAgICAgICBhLCBiID0gYiwgYSAlIGIKICAgIHJldHVybiBhCgpkZWYgc2lnbnVtKG4pOgogICAgaWYgbiA+IDA6IHJldHVybiAxCiAgICBpZiBuIDwgMDogcmV0dXJuIC0xCiAgICByZXR1cm4gMAoKZGVmIGphY29iaShhLCBwKToKICAgIGEsIHQgPSBhICUgcCwgMQogICAgd2hpbGUgYSA8PiAwOgogICAgICAgIHdoaWxlIGEgJSAyID09IDA6CiAgICAgICAgICAgIGEgLz0gMgogICAgICAgICAgICBpZiBwICUgOCBpbiAoMywgNSk6IHQgKj0gLTEKICAgICAgICBhLCBwID0gcCwgYQogICAgICAgIGlmIGEgJSA0ID09IDMgYW5kIHAgJSA0ID09IDM6IHQgKj0gLTEKICAgICAgICBhICU9IHAKICAgIHJldHVybiB0IGlmIHAgPT0gMSBlbHNlIDAKCmRlZiB1KHAsIHEsIG0sIG4pOgogICAgIyBudGggZWxlbWVudCBvZiBMdWNhcyBVKHAscSkgc2VxdWVuY2UgbW9kIG0KICAgICMgZm9yIHRoZSBiaXRzIG9mIG4gZnJvbSByaWdodCB0byBsZWZ0OgogICAgIyB1MiwgdjIsIGFuZCBxMiBkb3VibGUgYXQgZWFjaCBiaXQgYW5kIGFyZSBhZGRlZAogICAgIyB0byB0aGUgYWNjdW11bGF0b3JzIHUsIHYsIGFuZCBxIGF0IGVhY2ggMS1iaXQKICAgIGQsIHUyLCB2MiwgcTIgPSBwKnAgLSA0KnEsIDEsIHAsIHEKICAgIGlmIG4lMj09MTogdSx2LHEgPSAxLHAscQogICAgZWxzZTogdSx2LHEgPSAwLDIsMQogICAgd2hpbGUgbiA+IDE6CiAgICAgICAgdTIsIHYyLCBxMiwgbiA9IFwKICAgICAgICAgICAgKHUyKnYyKSVtLCAodjIqdjItMipxMiklbSwgKHEyKnEyKSVtLCBuLy8yCiAgICAgICAgaWYgbiUyID09IDE6CiAgICAgICAgICAgIHUsIHYgPSB1KnYyK3UyKnYsIHYqdjIrZCp1KnUyCiAgICAgICAgICAgIHUgPSAodS8yKSVtIGlmIHUlMj09MCBlbHNlICgodSttKS8yKSVtCiAgICAgICAgICAgIHYgPSAodi8yKSVtIGlmIHYlMj09MCBlbHNlICgodittKS8yKSVtCiAgICAgICAgICAgIHEgKj0gcTIKICAgIHJldHVybiB1CgpkZWYgcHJvdmVQcmltZShuKToKICAgIGYsIGZzLCBmcCwgciwgZCA9IDIsIFtdLCAxLCBuKzEsIDUKICAgIHdoaWxlIGZwKmZwIDwgbjoKICAgIAlpZiBmKmYgPiByOgogICAgCQlmcy5hcHBlbmQocikKICAgIAkJYnJlYWsKICAgICAgICB3aGlsZSByICUgZiA9PSAwOgogICAgICAgICAgICByIC89IGY7IGZwICo9IGYKICAgICAgICAgICAgaWYgZiBub3QgaW4gZnM6CiAgICAgICAgICAgICAgICBmcy5hcHBlbmQoZikKICAgICAgICBmICs9IDEKICAgIHdoaWxlIGphY29iaShkLCBuKSA8PiAtMToKICAgICAgICBkID0gKGFicyhkKSsyKSAqIHNpZ251bShkKSAqIC0xCiAgICBwLCBxID0gMSwgKDEtZCkvNAogICAgaWYgZ2NkKGQsIG4pID4gMTogcmV0dXJuIEZhbHNlCiAgICBpZiB1KHAsIHEsIG4sIG4rMSkgPD4gMDogcmV0dXJuIEZhbHNlCiAgICBmb3IgeCBpbiBmczoKICAgICAgICB3aGlsZSBUcnVlOgogICAgICAgICAgICBpZiBnY2QodShwLHEsbiwobisxKS94KSwgbikgPT0gMToKICAgICAgICAgICAgCXByaW50IGQsIHAsIHEsIHgsIHUocCwgcSwgbiwgKG4rMSkveCkKICAgICAgICAgICAgCWJyZWFrCiAgICAgICAgICAgIHAsIHEgPSBwICsgMiwgcCArIHEgKyAxCiAgICByZXR1cm4gVHJ1ZQoKcHJpbnQgcHJvdmVQcmltZSgxMCoqMTIrMzkpCnByaW50IHByb3ZlUHJpbWUoMTAqKjEyKzYxKQ==