BSGS算法
求关于x的方程a^x = b(mod p),gcd(a,p) = 0下的x;
算法流程:
令x = am -b
y^(am-b) = z(mod p)
y^am = zy^b (mod p)
枚举b = [0,m-1],map记录右边的值,枚举左边的a= [1,m+1]
每次查询右边map中是否有左边的值。O(sqrt(p))
模板:https://www.luogu.com.cn/problem/P3846
ll a,b,p;
ll qpw(ll a,ll b,ll p) {
a%=p;
ll ans = 1;
while(b) {
if(b & 1)ans = ans*a%p;
a = a*a%p;
b>>=1;
}
return ans%p;
}
map<ll,ll>mp;
ll BSGS(ll a,ll b,ll p) { //返回-1表示没找到
mp.clear();
if(b == 1) {
return 0;
}
ll ans=-1,m=sqrt(p)+1,xx,s=b;
for(int i=0; i<m; i++) {
mp[s] = i; //右边对应的b
s = 1ll*s*a%p;
}
xx = qpw(a,m,p),s=1; //左边
for(int i=1; i<=m+1; i++) {
s=1ll*s*xx%p;
if(mp.count(s)) {
ans = i*m-mp[s];
break;
}
}
if(ans < 0)return -1;
else return ans;
}
ex_BSGS : 若gcd(a,b) != 0
算法流程挺烦的,不管了 https://www.luogu.com.cn/problem/P4195
ll ex_BSGS(ll a,ll b,ll p) {
mp.clear();
if(b == 1)return 0;
ll cnt = 0,t=1,s,xx,m;
for(int d=gcd(a,p); d!=1; d=gcd(a,p)) {
if(b % d)return -1;
++cnt,b/=d,p/=d,t=1ll*t*a/d%p;
if(b == t)return cnt;
}
s=b,m=sqrt(p)+1;
for(int i=0; i<m; i++) {
mp[s] = i;
s=1ll*s*a%p;
}
xx = qpw(a,m,p),s=t;
for(int i=1; i<=m; i++) {
s=1ll*s*xx%p;
if(mp.count(s))return i*m-mp[s]+cnt;
}
return -1;
}