[拓展Bsgs] Clever - Y
阿新 • • 發佈:2018-12-31
題目連結 Clever - Y
題意
有同餘方程 \(X^Y \equiv K\ (mod\ Z)\),給定\(X\),\(Z\),\(K\),求\(Y\)。
解法
如題,是拓展 \(Bsgs\) 板子,部分學習內容在這裡 \((Click\ here)\)。
敲完板子就能獲得至少 5 倍經驗。
過程中瘋狂 \(WA\) 所以總結需要注意的幾點……
· 令 \(m = sqrt(p) + 1\) 比較保險,不然有的時候會列舉不到
· 在令 \(a\),\(p\) 互質的迴圈中,\(b = d\) 時及時返回是有必要的
· 同時在以上步驟中,\((a, p)\)
· \(map\) 慢的一批!慢的一批!手寫個效率有保證的類似雜湊表的東西
類似的題目
[Hdu 2815] Mod Tree
[Poj 2417] Discrete Logging
[CQOI2018] 破解D-H協議
程式碼……
#include <cmath> #include <cstdio> #include <vector> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long u64; class Hash_table { private: vector<u64> value; vector<pair<u64, u64> > funcn; public: inline void clear() { value.clear(), funcn.clear(); } inline void sortv() { sort(value.begin(), value.end()); } inline void push(u64 x, u64 p) { value.push_back(x), funcn.push_back(make_pair(x, p)); } inline bool find(u64 x) { int k = lower_bound(value.begin(), value.end(), x) - value.begin(); return (k != value.size()) && (value[k] == x); } inline int posi(u64 x) { for(int i = 0; i < funcn.size(); ++i) if( funcn[i].first == x ) return funcn[i].second; } } lg; inline u64 Fast_pow(u64 x, u64 p, u64 m) { u64 ans = 1; if( p < 0 ) return ans; for( ; p; x = x * x % m, p = p >> 1) if( p & 1 ) ans = x * ans % m; return ans; } inline u64 Ex_gcd(u64 a, u64 b, u64 &x, u64 &y) { if( !b ) { x = 1, y = 0; return a; } u64 d = Ex_gcd(b, a % b, y, x); y = y - a / b * x; return d; } inline u64 Gcd(u64 a, u64 b) { return !b ? a : Gcd(b, a % b); } inline u64 Inverse(u64 a, u64 p) { u64 x = 0, y = 0, g = Ex_gcd(a, p, x, y); return g == 1 ? (x + p) % p : -1ll; } inline u64 Solve_fun(u64 a, u64 b, u64 p) { u64 g = Gcd(a, p), inv = 1, x = 0, y = 0; if( b % g ) return -1ll; a = a / g, b = b / g, p = p / g; inv = Inverse(b, p), a = a * inv % p, b = 1; Ex_gcd(a, p, x, y), x = (x + p) % p; return ~inv ? x : -1ll; } inline u64 Ex_bsgs(u64 a, u64 b, u64 p) { u64 m = 1, d = 1, num = 0, base = 1, pow_a = 1, ans = -1; for(u64 g = Gcd(a, p); g != 1ll; g = Gcd(a, p), ++num) { if( num > 31 || b % g ) return -1ll; b = b / g, p = p / g, d = d * (a / g) % p; if( b == d ) return num + 1; } m = sqrt(p) + 1, base = Fast_pow(a, m, p), lg.clear(), lg.push(1ll, 0ll); for(u64 i = 1; i <= m + num; ++i) pow_a = pow_a * a % p, lg.push(pow_a, i); lg.sortv(); for(u64 tmp, i = 0; i <= m; ++i) { tmp = Solve_fun(d % p, b, p), d = d * base % p; if( ~tmp && lg.find(tmp) ) { ans = i * m + lg.posi(tmp) + num; break; } } return ans; } int main(int argc, const char *argv[]) { u64 a = 0, b = 0, p = 0, ans = 0; while( ~scanf("%lld%lld%lld", &a, &p, &b) ) if( p ) { ans = Ex_bsgs(a, b, p); ~ans ? printf("%lld\n", ans) : printf("No Solution\n"); } return 0; }
—— 我們還會繼續與人萍水相逢,為了新的別離。