def is_prime(n: int) -> bool: #ミラー–ラビン素数判定法 # https://qiita.com/srtk86/items/609737d50c9ef5f5dc59 # https://en.wikipedia.org/wiki/Strong_pseudoprime assert isinstance(n, int) and 0 < n if n == 2: return True if n == 1 or n & 1 == 0: return False d = (n - 1) >> 1 while d & 1 == 0: d >>= 1 # n-1=(2**s)*d (dは奇数) L=[a for a in (2, 325, 9375, 28178,450775, 9780504, 1795265022) if a=2**64: # これはwikiによる from random import randint L += [randint(1, n-1) for _ in range(100)] for a in L: # nが素数ならばa^d≡1 (mod p) もしくは t = d # a^((2^r)*d)≡-1 (mod p) が成立すべき y = pow(a, t, n) while t != n - 1 and y != 1 and y != n - 1: y = (y * y) % n t <<= 1 if y != n - 1 and t & 1 == 0: return False else: return True def findFactorRho(n): from math import gcd m = 1 << n.bit_length() // 8 for c in range(1, 99): def f(x): return (x * x + c) % n y, r, q, g = 2, 1, 1, 1 while g == 1: x = y for i in range(r): y = f(y) k = 0 while k < r and g == 1: ys = y for i in range(min(m, r - k)): y = f(y) q = q * abs(x - y) % n g = gcd(q, n) k += m r <<= 1 if g == n: g = 1 while g == 1: ys = f(ys) g = gcd(abs(x - ys), n) if g < n: if is_prime(g): return g elif is_prime(n // g): return n // g return findFactorRho(g) def prime_factors(n, return_e: bool = False): i = 2 ret = {} rhoFlg = 0 while i*i <= n: k = 0 while n % i == 0: n //= i k += 1 if k: ret[i] = k i += 1 + i % 2 if i == 101 and n >= 2 ** 20: while n > 1: if is_prime(n): ret[n], n = 1, 1 else: rhoFlg = 1 j = findFactorRho(n) k = 0 while n % j == 0: n //= j k += 1 ret[j] = k if n > 1: ret[n] = 1 if rhoFlg: ret = {x: ret[x] for x in sorted(ret)} return list(ret.keys()) def primitive_root(p: int) -> int: """素数pに対する何らかの原始根rを一つ求める (rの位数はp-1) https://manabitimes.jp/math/842 https://37zigen.com/primitive-root/ 最速ではない """ if p == 2: return 1 from random import randint p_1_pfs = prime_factors(p-1, return_e=False) cnt = 0 while cnt < 2*p: cnt += 1 cfr = randint(2, p-1) # candidates for r for pf in p_1_pfs: if pow(cfr, (p-1)//pf, p) == 1: # p-1//pfが位数候補 break else: # 全ての位数候補に対して、その否定がなされた。 return cfr else: raise AssertionError def discrete_logarithm(x, y, mod): """離散対数問題 x^k≡yとなるようなkを求める O(√mod)""" babys = {} sqrt = int(mod**0.5)+1 # baby-step x_baby = 1 for i in range(sqrt): babys[x_baby] = i # x^(sqrt-1)まで求めておく if x_baby == y: return i x_baby = x_baby * x % mod # giant-step x_giant = pow(x_baby, mod-2, mod) # x^(-sqrt) for i in range(1, sqrt+1): y = y * x_giant % mod if y in babys: # ここで√modずつ見ていく為に速い return babys[y] + i*sqrt return -1 # 原始根でない限り、必ず存在するとは言えない def _inv_gcd(a, b) -> tuple: """ 返り値は(gcd(a,b),x) (ただしxa≡g (mod b) 0<=x=0) m0 += b // s return (s, m0) def eea(a: int, b: int) -> tuple: """ ax+by=gcd(a,b)なる(x,y)を求める(拡張されたユークリッドの互除法) (extended_euclidean_algorithm)(元のユークリッドの互除法はgcdを求める手法を指す) https://qiita.com/drken/items/b97ff231e43bce50199a https://ja.wikipedia.org/wiki/ユークリッドの互除法 <-英語版が優秀すぎ https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm また、以上の話題は連分数展開とも関連があるらしい """ g, x = _inv_gcd(a, abs(b)) y = (b//abs(b))*(g-a*x)//abs(b) assert (g-a*x) % abs(b) == 0 return (x, y) def main(): import sys from math import gcd input = sys.stdin.buffer.readline T = int(input()) for _ in range(T): p, k, a = map(int, input().split()) g = primitive_root(p) y = discrete_logarithm(g, a, p) gkp = gcd(k, p-1) if y % gkp != 0: print(-1) continue z = (y//gkp)*eea(k//gkp, -(p-1)//gkp)[0] x = pow(g, z % (p-1), p) print(x) if __name__ == '__main__': main()