#include using namespace std; template class y_combinator { F f; public: y_combinator(F&& f) : f(std::forward(f)) {} template auto operator()(Args&&... args) const { return f(*this, std::forward(args)...); } }; using ll = long long; using u32 = unsigned int; using u64 = unsigned long long; using vi = vector; using vl = vector; using pii = pair; using pll = pair; template using vc = vector; template using vvc = vector>; template > using prique = priority_queue, U>; #define overload(a, b, c, d, e, ...) e #define len(x) (ll)(x.size()) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define rep1(n) for (ll _ = 0; _ < ll(n); _++) #define rep2(i, n) for (ll i = 0; i < ll(n); i++) #define rep3(i, a, b) for (ll i = ll(a); i < ll(b); i++) #define rep4(i, a, b, c) for (ll i = ll(a); i < ll(b); i += ll(c)) #define rep(...) overload(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__) #define rrep(i, n) for (ll i = ll(n) - 1; i >= 0; i--) template vector cumsum(const vector& a) { vector res(a.size() + 1); rep(i, a.size()) res[i + 1] = res[i] + a[i]; return res; } template void dedup(vector& a) { sort(all(a)), a.erase(unique(all(a)), a.end()); } template bool chmax(T& a, const S& b) { return a < static_cast(b) ? a = static_cast(b), 1 : 0; } template bool chmin(T& a, const S& b) { return a > static_cast(b) ? a = static_cast(b), 1 : 0; } namespace cppio { template struct is_tuple_like : false_type {}; template struct is_tuple_like> : true_type {}; template struct is_tuple_like> : true_type {}; template struct is_container : false_type {}; template struct is_container()))>> : bool_constant, string> && !is_same_v, char*> && !is_same_v, const char*> && !is_array_v>> {}; template void _in(T& x) { if constexpr (is_tuple_like::value) apply([](auto&... elems) { (_in(elems), ...); }, x); else if constexpr (is_container::value) { for (auto& e : x) _in(e); } else cin >> x; } template void _in_all(Ts&... args) { (_in(args), ...); } template void _out(const T& x) { bool first = true; if constexpr (is_tuple_like::value) { apply([&](const auto&... elems) { ((cout << (first ? "" : " "), _out(elems), first = false), ...); }, x); } else if constexpr (is_container::value) { for (const auto& e : x) { if (!first) cout << ' '; _out(e), first = false; } } else cout << x; } template void _print(const Ts&... args) { bool first = true; ((cout << (first ? "" : " "), _out(args), first = false), ...); } template void _out_no_el(const Ts&... args) { _print(args...); } template void _out_all(const Ts&... args) { _out_no_el(args...), cout << '\n'; } } // namespace cppio #define IN(...) cppio::_in_all(__VA_ARGS__) #define OUT(...) cppio::_out_all(__VA_ARGS__) #define INT(...) int __VA_ARGS__; IN(__VA_ARGS__) #define LL(...) ll __VA_ARGS__; IN(__VA_ARGS__) #define STR(...) string __VA_ARGS__; IN(__VA_ARGS__) #define CHR(...) char __VA_ARGS__; IN(__VA_ARGS__) #define DBL(...) double __VA_ARGS__; IN(__VA_ARGS__) #define VEC(type, name, size) vector name(size); IN(name) #define VV(type, name, h, w) vector> name(h, vector(w)); IN(name) #define RETURN(...) do { __VA_ARGS__; return; } while (0) bool Yes(bool b = true) { return OUT(b ? "Yes" : "No"), b; } bool No(bool b = true) { return Yes(!b), b; } bool YES(bool b = true) { return OUT(b ? "YES" : "NO"), b; } bool NO(bool b = true) { return YES(!b), b; } #ifdef ONLINE_JUDGE #define debug(...) (void(0)) #endif u64 splitmix64(u64 x) { static const u64 FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); x += FIXED_RANDOM; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return (x ^ (x >> 31)); } struct SplitMix64Hash { size_t operator()(ll x) const { return splitmix64(static_cast(x)); } }; template using HashMap = unordered_map; using HashSet = unordered_set; ll int_pow(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res *= a; a *= a; n >>= 1; } return res; } ll mod_pow(ll a, ll n, ll m) { ll res = 1; while (n) { if (n & 1) res *= a, res %= m; a *= a, a %= m; n >>= 1; } return res; } ll discrete_logarithm(ll a, ll b, ll m, ll alpha = 1) { ll add = 0; while (true) { ll g = std::gcd(a, m); if (g == 1) break; if (alpha == b) return add; if (b % g != 0) return -1; alpha *= a / g, alpha %= m; b /= g, m /= g; add++; } const int B = std::sqrt(m) + 10; const ll apb = mod_pow(a, B, m); ll val = alpha; HashMap mp; for (int p = 1; p <= (m + B - 1) / B; p++) { val *= apb, val %= m; if (mp.find(val) == mp.end()) mp[val] = p; } ll aq = b % m; int ans = m; for (int q = 0; q <= B; q++) { if (mp.find(aq) != mp.end()) { int p = mp[aq]; ans = std::min(p * B - q, ans); } aq *= a, aq %= m; } return ans == m ? -1 : ans + add; } #include using mint = atcoder::modint; void run_case() { LL(P, R, Q); mint::set_mod(P); const mint inv2 = mint::raw(2).inv(); while (Q--) { LL(A, B, C); const mint inv = mint::raw(A).inv(); const mint Z = (inv * B).pow(2) - 4 * inv * C; if (Z == 0) { mint t = -inv * B; t *= inv2; OUT(t.val()); continue; } if (Z.pow((P - 1) / 2) != 1) { OUT(-1); continue; } if (C == 0) { OUT(0, (mint(-B) * mint(A).inv()).val()); continue; } int k = discrete_logarithm(R, Z.val(), P); assert(k != -1 && k % 2 == 0); const mint RR = mint::raw(R).pow(k / 2); ll X = ((RR - inv * B) * inv2).val(); ll Y = ((-RR - inv * B) * inv2).val(); if (X > Y) swap(X, Y); assert(X != Y); OUT(X, Y); } } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); std::fixed(std::cout).precision(16); int t = 1; while (t--) run_case(); }