第一部分: BSGS详解
BSGS算法主要用来求这个问题:
求解关于 bbb 的方程
ab≡p(modm) a^b \equiv p \pmod{m} ab≡p(modm)
普通 BSGS 算法还需要满足 gcd(a,m)=1\gcd(a,m) =1gcd(a,m)=1。
解题思路如下:
设 g=⌈p⌉g=\lceil \sqrt{p} \rceilg=⌈p⌉ ,1≤i≤g 1\le i \le g\;1≤i≤g, 0≤j≤g\;\;0 \le j \le g0≤j≤g
我们把这个柿子变成这样:
aig≡paj(modm) a^{ig} \equiv pa^j \pmod{m}\ \ \ \ \ \ \ \ \ \ aig≡paj(modm)
先枚举 jjj ,把每一个 paj mod mpa^j \bmod mpajmodm 求出来放到 map 里面。
然后枚举 iii ,看看 aig mod ma^{ig} \bmod maigmodm 是不是在 map 里面。如果在,那么让 iii 最小,输出 im−map(ap mod m)iim-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;
}

121

被折叠的 条评论
为什么被折叠?



