結果
| 問題 |
No.981 一般冪乗根
|
| ユーザー |
semisagi
|
| 提出日時 | 2020-12-10 16:23:46 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 1,741 bytes |
| コンパイル時間 | 87 ms |
| コンパイル使用メモリ | 12,800 KB |
| 実行使用メモリ | 11,136 KB |
| 最終ジャッジ日時 | 2024-09-19 20:37:00 |
| 合計ジャッジ時間 | 39,418 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 6 WA * 37 RE * 1 |
ソースコード
def legendre(a, p):
return pow(a, (p - 1) // 2, p)
# https://rosettacode.org/wiki/Tonelli-Shanks_algorithm#Python
def tonelli(n, p):
assert legendre(n, p) == 1, "not a square (mod p)"
q = p - 1
s = 0
while q % 2 == 0:
q //= 2
s += 1
if s == 1:
result = pow(n, (p + 1) // 4, p)
return [result, p - result]
for z in range(2, p):
if p - 1 == legendre(z, p):
break
c = pow(z, q, p)
r = pow(n, (q + 1) // 2, p)
t = pow(n, q, p)
m = s
t2 = 0
while (t - 1) % p != 0:
t2 = (t * t) % p
for i in range(1, m):
if (t2 - 1) % p == 0:
break
t2 = (t2 * t2) % p
b = pow(c, 1 << (m - i - 1), p)
r = (r * b) % p
c = (b * b) % p
t = (t * c) % p
m = i
return [r, p - r]
memo = {}
def solve_two(a, n, p):
if a == 0:
return [0]
if n == 1:
return [a]
if legendre(a, p) != 1:
return []
if (a, n, p) in memo:
return memo[(a, n, p)]
result = []
for x in tonelli(a, p):
result += solve_two(x, n // 2, p)
memo[(a, n, p)] = result
return result
def extgcd(a, b):
if b == 0:
return (1, 0)
else:
x, y = extgcd(b, a % b)
return (y, x - (a // b) * y)
def solve_odd(a, n, p):
e = extgcd(n, p - 1)[0] % (p - 1)
return pow(a, e, p)
def solve(a, n, p):
e = 1
while n % 2 == 0:
n //= 2
e *= 2
a = solve_odd(a, n, p)
return solve_two(a, e, p)
T = int(input())
for _ in range(T):
p, k, a = map(int, input().split())
answer = solve(a, k, p)
if len(answer) == 0:
print(-1)
else:
print(answer[0])
semisagi