bsgs算法总结
北上广深算法
BS高神算法
现在要球解关于(x)的方程(y^xequiv z (mod p ))
然后(gcd(y,p)=1)
把(x)写成(x=am-b)的形式
(y^{am}equiv z imes y^b (mod p ))
(b)的取值只有([0,m)),然后可以算出来每一个取值后的结果,存在一个hash表里面
再枚举左边(a)判等,复杂度(O(max(m,p/m)))
显然,取(m=sqrt p)最优了
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<map>
#include<cmath>
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
ll y,z,p;
il ll pow(ll x,ll y){
ll ret=1;
while(y){
if(y&1)ret=ret*x%p;
x=x*x%p;y>>=1;
}return ret;
}
il ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
std::map<ll,ll>yyb;
int main(){
#ifdef xzz
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
#endif
int T=gi(),k=gi();
while(T--){
y=gi(),z=gi(),p=gi();
if(k==1)printf("%lld
",pow(y,z));
else if(k==2){
z%=p;
ll d=(y%p)?1:p;
if(z%d){puts("Orz, I cannot find x!");goto facai;}
else printf("%lld
",z*pow(y,p-2)%p);
}else{
if(y%p){
y%=p,z%=p;
if(z==1)
if(y==0){puts("Orz, I cannot find x!");goto facai;}
else{puts("0");goto facai;}
ll m=sqrt(p)+1;yyb.clear();
for(rg ll i=0,x=z%p;i<m;++i,x=x*y%p)yyb[x]=i;
for(rg ll i=1,x=pow(y,m),t=x;i<=m+1;++i,t=t*x%p){
if(yyb.find(t)==yyb.end())continue;
printf("%lld
",i*m-yyb[t]);
goto facai;
}
puts("Orz, I cannot find x!");
}else puts("Orz, I cannot find x!");
facai:;
}
}
return 0;
}
还有个天坑扩展BSGS
待填