#include #include #define rep(i,n) for(int i=0;i vi; typedef vector vl; typedef vector> vvi; typedef vector> vvl; typedef long double ld; typedef pair P; template ostream& operator<<(ostream& os, const static_modint& a) {os << a.val(); return os;} template ostream& operator<<(ostream& os, const dynamic_modint& a) {os << a.val(); return os;} template istream& operator>>(istream& is, static_modint& a) {long long x; is >> x; a = x; return is;} template istream& operator>>(istream& is, dynamic_modint& a) {long long x; is >> x; a = x; return is;} template istream& operator>>(istream& is, vector& v){int n = v.size(); assert(n > 0); rep(i, n) is >> v[i]; return is;} template ostream& operator<<(ostream& os, const pair& p){os << p.first << ' ' << p.second; return os;} template ostream& operator<<(ostream& os, const vector& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : " "); return os;} template ostream& operator<<(ostream& os, const vector>& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : ""); return os;} template ostream& operator<<(ostream& os, const set& se){for(T x : se) os << x << " "; os << "\n"; return os;} template ostream& operator<<(ostream& os, const unordered_set& se){for(T x : se) os << x << " "; os << "\n"; return os;} template ostream& operator<<(ostream& os, const atcoder::segtree& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template ostream& operator<<(ostream& os, const atcoder::lazy_segtree& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template void chmin(T& a, T b){a = min(a, b);} template void chmax(T& a, T b){a = max(a, b);} // Start 14:59 // Fermat's little theorem and Euler's theorem //(I) N = 0 mod B // M^L = 0 (M = 0 and L > 0) // M^L != 0 (M != 0 or(M = 0 and L = 0)) // N^(M^L) = 1 (M = 0 and L > 0) // N^(M^L) = 0 (M != 0 or(M = 0 and L = 0)) //(II) B = 1 // ans = 1 //(III) otherwise // a^(phi(B)) = 1 mod(B) // a^(phi(phi(B))) = 1 mod(phi(B)) // Start Implementation 15:15 // 15:41 Submission -> WA // int -> long long // 15:41 Submission -> WA // Euler's theorem is ng! a and B are now always coprime!! // regularity? // a_i = n^i mod B // at most B-length repetition // the length L is always divides B-1 ? <- False // B = _Prod p_i e_i // CRT? <- ( ; ; ) // the length L is always divides phi(B) ? <- ? // 16:22 break // 16:50 Restart // multiprecision // simply calculate N^(M^L) O(log(M^L)) = O(L log M) // 16:59 Submission -> WA // corner?? #include namespace mp = boost::multiprecision; using Bint = mp::cpp_int; template T pow_mod(T A, T N, T MOD){ T res = 1 % MOD; A %= MOD; while(N){ if(N & 1) res = (res * A) % MOD; A = (A * A) % MOD; N >>= 1; } return res; } template T pow_simple(T A, T N){ T res = 1; while(N){ if(N & 1) res = (res * A); A = (A * A); N >>= 1; } return res; } int main(){ int n, m, l; cin >> n >> m >> l; int b = -1; { // ok >= b, ng < b int ok = 1000000001, ng = 0; while(ok - ng > 1){ int mid = (ok + ng) / 2; cout << "? " << mid << ' ' << 1 << "\n"; flush(cout); int res; cin >> res; if(res < mid) ok = mid; else ng = mid; } b = ok; } assert(n % b != 0); if(b == 1){ cout << "! 0\n"; return 0; } n %= b; if(n == 0){ if(m == 0 and l > 0) cout << "! 1\n"; else cout << "! 0 \n"; return 0; } Bint e = pow_simple(m, l); Bint ans = pow_mod(n, e, b); cout << "! " << ans << "\n"; return 0; }