这道题应该算是数论里面比较难的一道题,我顺便借此学了BSGS(Baby Steps Giant Steps),又称力拔盖世算法(手动滑稽).刚开始看到这道题只能感到深深的无助,完全不会做…对于一道数论题如果不会做的话,大家还是可以尝试很多特判骗分的,这道题就有很多特判.从小角度切入,深入了解问题,往往是很重要的.
由于不知道怎么打出一堆数学符号,所以很难与大家分享我的题解。我在网上找了另一个人的博客,他这道题讲的很清晰,我学BSGS也是从他那里学来的,希望大家能够学会。这篇博客就当提供一段简洁明了,逻辑清晰的代码(真的挺短,只用了费马小定理通过快速幂求逆元).
BSGS:http://blog.youkuaiyun.com/clove_unique/article/details/50740412
bzoj3122:http://blog.youkuaiyun.com/clove_unique/article/details/50776001
#include<stdio.h>
#include<map>
#include<cmath>
using namespace std;
typedef long long dnt;
map<dnt,dnt> has;
dnt p,a,b,x1,t,T,ny,nia,ans,oops;
inline const dnt read(){
register dnt f=1,x=0;
register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline dnt pow(dnt base,dnt tmp){
dnt a=1;
while(tmp){
if(tmp&1) a=a*base%p;
base=base*base%p;
tmp=tmp>>1;
}
return a;
}
inline dnt BSGS(dnt a,dnt b){
dnt m=ceil(sqrt(p)),am=pow(a,m),mul=1,val=b%p;
has.clear();
has[val]=0;
for(dnt j=1;j<=m;j++){
mul=mul*a%p;
val=mul*b%p;
has[val]=j;
}
mul=1;
for(dnt i=1;i<=m;i++){
mul=mul*am%p;
if(has[mul]) return i*m-has[mul]+1;
}
return -1;
}
int main(){
T=read();
while(T--){
p=read(),a=read(),b=read(),x1=read(),t=read();
if(t==x1) {printf("1\n");continue;}
if(!a){
if(b!=t) printf("-1\n");
else printf("2\n");
continue;
}
if(a==1){
if(!b) printf("-1\n");
else{
ny=pow(b,p-2);
ans=((t-x1)%p+p)%p*ny%p;
printf("%lld\n",ans+1);
}
continue;
}
nia=pow(a-1,p-2);
oops=(t+b%p*nia%p)%p*pow(x1+b%p*nia%p,p-2)%p;
printf("%lld\n",BSGS(a,oops));
}
}

本文深入讲解了BSGS(Baby Steps Giant Steps)算法,并通过一道数论难题演示了其应用过程。文章提供了简洁易懂的代码实现,利用费马小定理通过快速幂求逆元,帮助读者掌握这一高效解决离散对数问题的方法。
987

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



