baby step giant step
概要
素数$p$と$0\leq a,b< p $について,$a^x = b \mod p$となる$x$を求める.
計算量
$O(\sqrt{p} \log \sqrt{p})$
ソースコード
long extgcd(long a,long b,long & x,long & y){
long d = a;
if(b != 0) {
d = extgcd(b,a%b,y,x);
y -= (a/b) * x;
}else{
x = 1; y = 0;
}
return d;
}
long mod_inverse(long a,long m){
long x,y;
extgcd(a,m,x,y);
return (m + x % m) % m;
}
int modPow(long a, long n, long p) {
if (n == 0) return 1; // 0乗にも対応する場合
if (n == 1) return a % p;
if (n % 2 == 1) return (a * modPow(a, n - 1, p)) % p;
long t = modPow(a, n / 2, p);
return (t * t) % p;
}
long iroot(long y,int n){
//x^n <= yとなる最大のn
long ok = 0;
long ng = y+1;
while(abs(ok-ng)>1){
long mid = (ok+ng)/2;
long x = 1;
bool inf = false;
for(int i=0;i<n;i++){
if(((long)1e18)/x < mid)inf = true;
x *= mid;
}
if(inf||x>y){
ng = mid;
}else{
ok = mid;
}
}
return ok;
}
long BSGS(long a,long b,long p){
/* a^x = b mod p となるようなxを求める */
long x = -1;
long m = iroot(p,2)+1;
map<long,long> mp;
long ax = 1;
for(long i=0;i<=m;i++){
mp[ax] = i;
ax = (ax*a) % p;
}
/*
a^(im+j) = b
a^j = b(a^-m)^i
*/
long am = modPow(mod_inverse(a,p),m,p);
for(long i=0;i<=m;i++){
long d = (modPow(am,i,p)*b) % p;
if(mp.count(d)){
if(i==0&&mp[d]==0)continue;
x = i*m + mp[d];
break;
}
}
return x;
}