BSGS算法
BSGS算法使用来求解\(x\)的方程
\[ x ^ y \equiv z\pmod p \]
其中\(gcd(x, p) = 1\), 我们将\(y\)写做一个\(am - b\)的形式, 其中\(a \in (1, m + 1]\), \(b \in [0, m)\)
那么这样, 原式就变成了
\[ \begin{aligned} x^{am - b} &\equiv z \pmod p\\ x^{am} &\equiv z * x ^ b \pmod p \end{aligned} \]
我们枚举每一个\(b\), 将\(z * x ^ b\)存进\(hash\)或者\(map\)之类的东西
之后对于左边枚举每一个\(a\), 如果\(x ^ {am} \% p\)在\(hash\)或者\(map\)中, 答案就为\(a * m - mp[x ^ {am} \% p]\)
复杂度为\(O(max(m, p / m))\), 易证得\(m\)为\(\sqrt{p}\)的时候最优
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <map>
#define itn int
#define reaD read
using namespace std;
int p, x, y, s, m;
map<int, int> mp;
inline int read()
{
int x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
}
int fpow(int x, int k)
{
int res = 1;
while(k)
{
if(k & 1) res = 1ll * res * x % p;
x = 1ll * x * x % p;
k >>= 1;
}
return res;
}
int main()
{
p = reaD(); x = read(); y = read(); m = sqrt(p) + 1; s = y;
for(int i = 0; i < m; i++) mp[s] = i, s = 1ll * s * x % p;
s = 1; int t = fpow(x, m);
for(int i = 1; i <= m + 1; i++)
{
s = 1ll * s * t % p;
if(mp.count(s))
{
printf("%d\n", i * m - mp[s]);
return 0;
}
}
puts("no solution");
return 0;
}
ExBSGS算法
好像所有有\(Ex\)的算法似乎都是在不互质的情况下诶
这里, \(ExBSGS\)是用来处理\(gcd(x, p) != 1\)的情况的, 我们可以有这样一个式子, 设\(gcd(x, p) = d\)
\[ <Empty \space Math \space Block> \]