BSGS(大步小步)算法学习笔记
BSGS(大步小步)算法学习笔记
前置芝士
会取模运算就行啦!
正文部分
拔山盖世 算法用于求解 中 的值。
设 ,,,。
然后简单化一下:
因为 只有 个取值,可以先枚举 ,求出所有的 并使用 或 存储,然后枚举 ,求出 ,查找是否有与之相等的 ,若有则 即为合法的 值。不算 或 的化,复杂度 。
CODE
int Pow(int x, int k, int p, int r = 1) {
for (; k; k >>= 1, x = x * x % p) {
if (k & 1) r = r * x % p;
}
return r;
}
int bsgs(int a, int b, int p) {
b %= p, a %= p;
map<int, int> m;
int t = ceil(sqrt(p)), k = 1;
for (int i = 0; i < t; i ++, k = k * a % p) {
m[k * b % p] = i;
}
a = Pow(a, t, p), k = a;
for (int i = 1; i <= t; i ++, k = k * a % p) {
if (m.find(k) == m.end()) continue;
if (i * t - m[k] >= 0) return i * t - m[k];
}
return -1;
}exBSGS
使用 有一个限制条件,即 , 就是为了解决这个问题。
考虑 、 不互质时怎么做,设 ,,,易得 :
得到有解的条件:。 然后继续瞎搞一波:
每次使 $b = \dfrac{b}{g} \times a’^{-1} p = p’$,缩小问题范围,一直做到 , 互质即可 求解。注意 的指数变为 。
CODE
int Pow(int x, int k, int p, int r = 1) {
for (; k; k >>= 1, x = x * x % p) {
if (k & 1) r = r * x % p;
}
return r;
}
void exgcd(int a, int b, int &x, int &y) {
if (b == 0) {x = 1, y = 0; return;};
exgcd(b, a % b, x, y);
int t = y; y = x - (a / b) * y, x = t;
}
int Inv(int x, int p, int a = 0, int b = 0) {
return exgcd(x, p, a, b), (a % p + p) % p;
}
int gcd(int a, int b) {
return (!b ? a : gcd(b, a % b));
}
int bsgs(int a, int b, int p) {
b %= p, a %= p;
map<int, int> m;
int t = ceil(sqrt(p)), k = 1;
for (int i = 0; i < t; i ++, k = k * a % p) {
m[k * b % p] = i;
}
a = Pow(a, t, p), k = a;
for (int i = 1; i <= t; i ++, k = k * a % p) {
if (m.find(k) == m.end()) continue;
if (i * t - m[k] >= 0) return i * t - m[k];
}
return -1;
}
int exbsgs(int a, int b, int p) {
b %= p, a %= p;
if(b == 1 || p == 1)return 0;
int g = gcd(a, p), s = 0, c = 1;
for (; g > 1; g = gcd(a, p)) {
if (b % g != 0) return -1;
b /= g, p /= g, (c *= a / g) %= p, s ++;
if (b == c) return s;
}
int res = bsgs(a, b * Inv(c, p), p);
return (~res ? res + s : res);
}参考:OI Wiki,https://mancityfc.blog.luogu.org/solution-p3846,cqh’s blog 。
BSGS(大步小步)算法学习笔记
https://ybwa.github.io/p/17d3f61c/