破解D-H协议
题目背景:
分析:BSGS
显然我们要做的就是对于一个,求出对应的x,然后再发现数据范围是int以内,那么显然直接BSGS就可以了,并且,因为p是质数那么显然gcd(A, p) = 1那么直接上非扩展的就可以了。复杂度O(Tn1/2)
Source:
/* created by scarlyw */ #include <cstdio> #include <string> #include <algorithm> #include <cstring> #include <iostream> #include <cmath> #include <cctype> #include <vector> #include <set> #include <queue> inline char read() { static const int IN_LEN = 1024 * 1024; static char buf[IN_LEN], *s, *t; if (s == t) { t = (s = buf) + fread(buf, 1, IN_LEN, stdin); if (s == t) return -1; } return *s++; } ///* template<class T> inline void R(T &x) { static char c; static bool iosig; for (c = read(), iosig = false; !isdigit(c); c = read()) { if (c == -1) return ; if (c == '-') iosig = true; } for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x; } //*/ const int OUT_LEN = 1024 * 1024; char obuf[OUT_LEN], *oh = obuf; inline void write_char(char c) { if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf; *oh++ = c; } template<class T> inline void W(T x) { static int buf[30], cnt; if (x == 0) write_char('0'); else { if (x < 0) write_char('-'), x = -x; for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48; while (cnt) write_char(buf[cnt--]); } } inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); } /* template<class T> inline void R(T &x) { static char c; static bool iosig; for (c = getchar(), iosig = false; !isdigit(c); c = getchar()) if (c == '-') iosig = true; for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x; } //*/ long long g, mod, t, x, y; const int h_mod = 999979; inline long long mod_pow(long long a, long long b) { long long ans = 1; for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod; return ans; } struct node { long long val, key; node() {} node(long long val, long long key) : val(val), key(key) {} } ; std::vector<node> h[h_mod]; std::vector<int> stack; bool vis[h_mod]; inline void insert(long long pos, long long i) { int p = pos % h_mod; if (vis[p] == false) stack.push_back(p), vis[p] = true; h[p].push_back(node(pos, i)); } inline long long query(long long x) { int p = x % h_mod; for (int i = 0; i < h[p].size(); ++i) { node *e = &h[p][i]; if (e->val == x) return e->key; } return -1; } inline long long solve(long long x, long long g, long long mod) { long long c = sqrt(mod), p = 1; for (int i = 0; i < stack.size(); ++i) h[stack[i]].clear(), vis[stack[i]] = false; stack.clear(); for (long long i = 0; i < c; ++i, p = p * g % mod) { if (p == x) return i; insert(p * x % mod, i); } long long cur = 1, t; for (long long i = c; i - c + 1 <= mod - 1; i += c) { cur = cur * p % mod, t = query(cur); if (t != -1) return i - t; } } int main() { freopen("crack.in", "r", stdin); freopen("crack.out", "w", stdout); R(g), R(mod), R(t); while (t--) R(x), R(y), std::cout << mod_pow(y, solve(x, g, mod)) << '\n'; return 0; } /* 3 31 3 16 27 21 3 26 9 */