用来求解如下同余方程x的最小正整数解:
p为质数,a、b、p已知,且 (如果a、b大于p,则对他们取模)
模板:(p为素数)
/*********************解法***********************/
//BSGS算法
//求 a^x === b(mod p) 中的x值-----------当前p为素数
//实际运用中用自己的hash表代替map可防TLE
/*********************解法***********************/
LL
LL BSGS(LL a, LL b, LL p){
a %= p; b %= p;
map<LL, LL>h;
LL m = ceil(sqrt(p)), x, y, d, t = 1, v = 1;
for(LL i = 0; i < m; i++){
if(h,count(t)) h[t] = min(h[t], i);
else h[t] = i;
t = (t * a) % p;
}
for(LL i = 0; i < m; i++){
d = exgcd(v, p, x, y);
x = (x * b/d % p + p) % p;
if(h.count(x)) return i * m + h[x];
v = (v * t) % p;
}
return -1;
}
扩展(p为非素数)
模板:
/*********************解法***********************/
//BSGS算法
//求 a^x === b(mod p) 中的x值-----------当前p为合数
//注意:a,b,p分别为1,1,1时,结果x为1而非0
/*********************解法***********************/
LL exBSGS(LL a, LL b, LL ){
a %= p; b %= p;
LL res = 1;
for(LL i = 0; i <= 50; i++){
if(res == b) return i;
res = (res * a) % p;
} //枚举比较小的
LL x, y, d, , v = 1, cnt = 0;
while(d = gcd(a, p) != 1){
if(b % d) return -1;
b /= d, p /= d;
v = (v * (a/d)) % p;
cnt++;
} //约分直到(a,p) == 1;
map<LL, LL> h;
LL m = ceil(sqrt(p)), t = 1;
for(LL i = 0; i < m; i++){
if(h.count(t)) h[t] = min(h[t], i);
else h[t] = i;
t = (t * a) % p;
}
for(LL i = 0; i < m; i++){
d = exgcd(v, p, x, y);
x = ((x * (b/d)) % p + p) % p;
if(h.count(x)) return i * m + h[x] + cnt;
v = (v * t) % p;
}
return -1;
}