洛谷【數競黨出的數論賽】U46278 按鈕
阿新 • • 發佈:2018-12-18
大膽猜結論:k^x≡1 mod m,答案就是最小正x
直接EXBSGS套上,明顯最小解為0,所以答案是次小解,雖然我總覺得我的是錯的但它就是過了……
EXBSGS盜的某位大爺的板
#include<math.h> #include<stdio.h> #include<string.h> #include <iostream> #include<algorithm> #define N 140142 using namespace std; typedef long long ll; struct Hash_Set { ll head[N], next[N], X[N], val[N], tot; void clear() { memset(head, 0, sizeof(head)); memset(next, 0, sizeof(next)); memset(val, -1, sizeof(val)); memset(X, 0, sizeof(X)); tot = 0; } ll& operator [](ll x) { ll index = x%N; for (ll i = head[index]; i; i = next[i]) { if (X[i] == x) return val[i]; } next[++tot] = head[index]; head[index] = tot; X[tot] = x; return val[tot]; } }hash; ll pow(ll x, ll y, ll mod) { ll ret = 1; while (y) { if (y & 1) ret = ret*x%mod; x = x*x%mod; y >>= 1; } return ret; } ll gcd(ll a, ll b) { ll t = a%b; while (t) { a = b, b = t; t = a%b; } return b; } void exgcd(ll a, ll b, ll &x, ll &y) { if (!b) x = 1, y = 0; else { exgcd(b, a%b, y, x); y -= a / b*x; } } ll inv(ll t, ll mod) { ll x, y; exgcd(t, mod, x, y); return (x%mod + mod) % mod; } ll BSGS(ll A, ll B, ll C) { hash.clear(); ll bk = ceil(sqrt(C)), i, j, k, D, temp; for (i = 0, D = 1; i < bk; i++, D = D*A%C) { if (hash[D] == -1) hash[D] = i; } temp = inv(D, C); bool fg = 0; for (i = 0, k = B; i <= bk; i++, k = k*temp%C) { if (hash[k] != -1) { if(!fg) { fg = 1; } else return i*bk + hash[k]; } } return -1; } ll EXBSGS(ll A, ll B, ll C) { if(C==1) { if(!B) return 0; else return -1; } ll lg = ceil(log(C*1.0) / log(2)), i, k, mod; for (i = 0, k = 1; i <= lg; i++, k = k*A%C); i = 0, mod = C; while ((k = gcd(A, mod)) != 1) { if (B%k) return -1; B /= k, mod /= k; i++; } ll ret = BSGS(A, B*inv(pow(A, i, mod)*inv(C / mod, mod) % mod, mod) % mod, mod); if (ret != -1) return ret + i; else return -1; } int main() { ll A, C; cin >> C >> A; ll ans = EXBSGS(A, 1, C); if(ans >= 0) cout << ans; else puts("Let's go Blue Jays!"); return 0; }