第一部分: BSGS详解
BSGS算法主要用来求这个问题:
求解关于 b b b 的方程
a b ≡ p ( m o d m ) a^b \equiv p \pmod{m} ab≡p(modm)
普通 BSGS 算法还需要满足 gcd ( a , m ) = 1 \gcd(a,m) =1 gcd(a,m)=1。
解题思路如下:
设 g = ⌈ p ⌉ g=\lceil \sqrt{p} \rceil g=⌈p⌉ , 1 ≤ i ≤ g 1\le i \le g\; 1≤i≤g, 0 ≤ j ≤ g \;\;0 \le j \le g 0≤j≤g
我们把这个柿子变成这样:
a i g ≡ p a j ( m o d m ) a^{ig} \equiv pa^j \pmod{m}\ \ \ \ \ \ \ \ \ \ aig≡paj(modm)
先枚举 j j j ,把每一个 p a j m o d m pa^j \bmod m pajmodm 求出来放到 map 里面。
然后枚举 i i i ,看看 a i g m o d m a^{ig} \bmod m aigmodm 是不是在 map 里面。如果在,那么让 i i i 最小,输出 i m − m a p ( a p m o d m ) i im-map_{(a^p \bmod m)^i} im−map(apmodm)i。
或者上面两个操作倒过来也可以。
答案就出来了。
对于这一道题,我们就可以用这种算法。还要注意读入的顺序和每一个变量的意义哦。
第二部分:代码实现
#include<cstdio>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
map<ll,ll>lot;//存储
int main()
{
ll a,b,p;
scanf("%lld%lld%lld",&p,&a,&b);//读入
ll m=ll(sqrt(p))+1;ll tmp=b,ttmp=1;
if(a%p==0)
{
puts("no solution");
return 0;
}//特判,如果a把模数除尽了那么根本没有答案
lot[m]=0;
for(ll i=1;i<=m;i++)//第一次循环
{
tmp=(tmp*a)%p;//这个记下标
ttmp=(ttmp*a)%p;//这个记 a^m%p
lot[tmp]=i;//赋值
}
ll cnt=1;//这个也是记录下标的
for(ll i=1;i<=m;i++)//第二次循环
{
cnt=(cnt*ttmp)%p;//更新
if(lot[cnt]) {printf("%lld\n",(i*m-lot[cnt]+2*p)%p);return 0;}//如果找到了符合的那么输出
}
puts("no solution");//没找到符合的,无解
return 0;
}