BSGS
做起来超级休闲的
求解\(a^x \equiv b (\mod p)\)
复杂度是\(\sqrt p\)
首先考虑,如何暴力
直接暴力枚举\(<p\)的指数
\(a^{p-1} \equiv 1(\mod p)\)
那么就是一个循环节了.
考虑如何在\(\sqrt p\)时间内解决这个问题.
指数\(x\)可以拆成\(k * t - m(t = \sqrt{p}), 0<=m<=t,1<=k<=\frac pt\)
\(a^{k*t - m} \equiv b(\mod p)\)
\(\frac {a^{k*t}}{a^m }\equiv b(\mod p)\)
\(a^{k*t}\equiv b * a^m(\mod p)\)
\(a^{k*t}b'\equiv a^m(\mod p)\)
\(b'\)是\(b\)的逆元.
其实把b放后面也可以啦,我可能是ZZ了.>>_<<
然后直接暴力枚举\(k\),用hash存下\(a^m\)的值,然后就可以\(O(\sqrt p)\)做了
附上代码 (SDOI2011 计算器)
/*gzy is a big B*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
using std::min;
using std::max;
using std::swap;
using std::__gcd;
#define int long long
inline int gi() {int x = 0,f = 1;char c = gc;while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;}
void print(ll x) {if(x < 0) pc('-') , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + '0');}
void Sub1(int a , int b , int mod) {
int ans = 1;
for(int now = a;b;b >>= 1,now = now * now % mod)
if(b & 1) ans = ans * now % mod;
print(ans);pc('\n');
}
int exgcd(int a , int b,int &x,int &y) {
if(!b) {
x = 1;y = 0;
return a;
}
int g = exgcd(b ,a % b,x , y);
int tmp = x;
x = y;
y = tmp - a / b * y;
return g;
}
void Sub2(int a,int z,int p) {
int x , y;
int g = exgcd(a , p,x , y);
if(z % g) {puts("Orz, I cannot find x!");return;}
p /= g;
x = x * z / g;
x = x % p + p;
x = x % p;
print(x);pc('\n');
return;
}
std::map<int , int> mp;
int fp(int a , int b, int mod) {
int ans = 1;
for(int now = a;b;b >>= 1 , now = now * now % mod)
if(b & 1) ans = ans * now % mod;
return ans;
}
int mul(int x, int y,int p) {return 1ll * x * y % p;}
int BSGS(int a , int b , int p) {
int M = ceil(sqrt(p)) , base = fp(a , M , p) , g = __gcd(a , p);if(g != 1) return -1;
mp.clear();
for(int i = 0 , now = b;i <= M;++ i) {
mp[now] = i + 1;
now = now * a % p;
}
for(int i = 1 , now = base;i <= M;++ i) {
if(mp[now]) return i * M - mp[now] + 1;
now = now * base % p;
}
return -1;
}
void Sub3(int a , int b , int c) {
b %= c;
int ans = BSGS(a , b, c);
ans == -1 ? puts("Orz, I cannot find x!") : (print(ans) , pc('\n'));
return;
}
main() {
// freopen("1.in","r",stdin);
int T = gi() , opt = gi();
while(T --) {
int a = gi() , b = gi(), c = gi();
if(opt == 1) Sub1(a , b, c);
else if(opt == 2) Sub2(a , b, c);
else Sub3(a , b, c);
}
return 0;
}