a i t − j ≡ b ( m o d p ) a^{it-j}\equiv b(mod\ p) ait−j≡b(mod p)
a i t ≡ b a j ( m o d p ) a^{it}\equiv ba^j(mod\ p) ait≡baj(mod p)
inline int solve_BSGS(const int &a, const int &b, const int &p)
{
int t = ceil(sqrt(p));
std::map<int, int> hash;
//map实现hash表
hash.clear();
int tmp = b;
for (int i = 1; i <= t; ++i)
{
tmp = 1LL * tmp * a % p;
hash[tmp] = i;
}
//插入b*a^j
int pw = qpow(a, t, p);
tmp = pw;
for (int i = 1; i <= t; ++i)
{
if (hash.find(tmp) != hash.end())
return i * t - hash[tmp];
tmp = 1LL * tmp * pw % p;
}
//查询a^(it)
return -1; //返回无解
}
a x + p y = b a^x+py=b ax+py=b
a x − 1 a a 1 + p a 1 y = b a 1 a^{x-1}\frac{a}{a_1}+\frac{p}{a_1}y=\frac{b}{a_1} ax−1a1a+a1py=a1b
a x − 2 a 2 a 1 a 2 + p a 1 a 2 y = b a 1 a 2 a^{x-2}\frac{a^2}{a_1a_2}+\frac{p}{a_1a_2}y=\frac{b}{a_1a_2} ax−2a1a2a2+a1a2py=a1a2b
a x − n a n a 1 a 2 … a n + p a 1 a 2 … a n y = b a 1 a 2 … a n a^{x-n}\frac{a^n}{a_1a_2\dots a_n}+\frac{p}{a_1a_2\dots a_n}y=\frac{b}{a_1a_2\dots a_n} ax−na1a2…anan+a1a2…anpy=a1a2…anb
a x − n a ′ ≡ b ′ ( m o d p ′ ) a^{x-n}a'\equiv b'(mod\ p') ax−na′≡b′(mod p′)
a x − n ≡ b ′ ( a ′ ) − 1 ( m o d p ′ ) a^{x-n}\equiv b'(a')^{-1}(mod\ p') ax−n≡b′(a′)−1(mod p′)
然后就可以用互质的方法解决了。
可以发现,每次在 p p p 中除去一个最大公约数,每次都会有至少同一个质因子的次数减少 1 1 1,那么在int
范围内, n n n 最多只会取到 30 30 30。
以上两个情况的时间复杂度均为 O ( p log 2 p ) O(\sqrt{p}\log_2{\sqrt p}) O(plog2p),因为用map实现哈希,可以做到更优秀。
有一些值得注意的地方:
模板题:SP3105 MOD - Power Modulo Inverted
洛谷链接:https://www.luogu.org/problemnew/show/SP3105
代码:
//map水过
#include
#include
#include
#include
#include
#include
#include
#include
int a, p, b;
inline int qpow(int b, int p, const int &mod)
{
int res = 1;
for (; p; p >>= 1, b = 1LL * b * b % mod)
if (p & 1)
res = 1LL * res * b % mod;
return res;
}
inline int ex_gcd(const int &a, const int &b, int &x, int &y)
{
if (!b)
return x = 1, y = 0, a;
int res = ex_gcd(b, a % b, y, x);
return y -= a / b * x, res;
}
inline int solve_equ(const int &a, const int &b, const int &c)
{
int x, y;
int d = ex_gcd(a, b, x, y);
if (c % d != 0) return -1;
int mod = b / d;
return (1LL * c / d * x % mod + mod) % mod;
}
inline int solve_BSGS(const int &a, const int &b, const int &p)
{
int t = ceil(sqrt(p));
std::map<int, int> hash;
hash.clear();
int tmp = b;
for (int i = 1; i <= t; ++i)
{
tmp = 1LL * tmp * a % p;
hash[tmp] = i;
}
int pw = qpow(a, t, p);
tmp = pw;
for (int i = 1; i <= t; ++i)
{
if (hash.find(tmp) != hash.end())
return i * t - hash[tmp];
tmp = 1LL * tmp * pw % p;
}
return -1;
}
inline bool check()
{
int k = 1 % p;
for (int i = 0; i <= 40; ++i)
{
if (k == b)
return printf("%d\n", i), true;
k = 1LL * k * a % p;
}
if (!a)
return puts("No Solution"), true;
return false;
}
int main()
{
while (scanf("%d%d%d", &a, &p, &b), a || p || b)
{
a %= p, b %= p;
if (check())
continue;
int d;
int ap = 1, n = 0;
bool flg = false;
while ((d = std::__gcd(a, p)) != 1)
{
++n;
ap = 1LL * ap * (a / d) % p;
p /= d;
if (b % d)
{
flg = true;
break;
}
b /= d;
}
if (flg)
puts("No Solution");
else
{
int res = solve_BSGS(a, 1LL * b * solve_equ(ap, p, 1) % p, p);
if (res == -1)
puts("No Solution");
else
printf("%d\n", res + n);
}
}
return 0;
}