版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83512195
正题
BSGS,Baby Step Giant Step 。
是用来解决类似于,一类问题的。
如果,那么对于,根据费马小定理,我们可以令对p-1取mod,对答案没有影响,并且保证了答案在这个范围之内。
我们可以令,得到,
转移一下,得到
我们把右式式处理出来放进一个std::map里面,然后让左式去找,找到的第一个就是答案。
void BSGS(){
m=ceil(sqrt(double(p)));
f[b]=0LL;
for(int j=1;j<=m;j++){
(b*=a)%=p;
f[p]=j;
}
long long data=ksm(a,m),A=1;
for(int i=1;i<=m;i++){
(A*=data)%=p;
if(f[A]){
printf("%lld",i*m-f[A]);
return ;
}
}
printf("No solution");
}
如果呢?
这时候又要请出我们大名鼎鼎的扩展欧几里得解决问题了。
我们先看一个式子:如果,那么
这个很显然,一移项就可以知道了。
,这时,经过不断得除以d,使得新的模数和a互质即可。
然后,如果,只有一个解那就是x=k
如果b不整除,那么没有解。
最后,也是把看成一个常数,做一遍普通的BSGS
void exBSGS(){
a=(a%p+p)%p;
b=(b%p+p)%p;
long long d,prod,k=0;
while((d=gcd(a,p)!=1)){
if(b%d==1) {printf("No solution");return ;}
b/=d;p/=d;prod=prod*a/d%p;k++;
if(b==k) {printf("%lld",k);return ;}
}
m=ceil(sqrt(double(p)));
f[b]=0LL;
for(int j=1;j<=m;j++){
(b*=a)%=p;
f[p]=j;
}
long long data=ksm(a,m),A=prod;
for(int i=1;i<=m;i++){
(A*=data)%=p;
if(f[A]){
printf("%lld",i*m-f[A]+k);
return ;
}
}
printf("No solution");
}