bsgs算法总结
bsgs算法总结
北上广深算法
BS高神算法
现在要球解关于\(x\)的方程\(y^x\equiv z\ (\mod p\ )\)
然后\(\gcd(y,p)=1\)
把\(x\)写成\(x=am-b\)的形式
\(y^{am}\equiv z\times 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\n",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\n",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\n",i*m-yyb[t]);
goto facai;
}
puts("Orz, I cannot find x!");
}else puts("Orz, I cannot find x!");
facai:;
}
}
return 0;
}
还有个天坑扩展BSGS
待填
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。