大步小步(bsgs)
!!
求
a
x
≡
b
(
m
o
d
p
)
a^x\equiv b(mod \quad p)
ax≡b(modp)中的x(最小非负整数),其中p为素数
设
m
=
p
向
上
取
整
m=\sqrt{p} 向上取整
m=p向上取整
x
=
k
m
−
q
,
k
∈
[
1
,
m
]
,
q
∈
[
0
,
m
]
x=km-q,k\in[1,m],q\in[0,m]
x=km−q,k∈[1,m],q∈[0,m]
则
a
x
≡
a
k
m
−
q
≡
b
(
m
o
d
p
)
a^x\equiv a^{km-q}\equiv b(mod \quad p)
ax≡akm−q≡b(modp)
所以
(
a
m
)
k
≡
b
∗
a
q
(
m
o
d
p
)
(a^m)^k\equiv b*a^q(mod \quad p)
(am)k≡b∗aq(modp)
先用map存下所有的
b
∗
a
i
(
i
∈
[
0
,
m
]
)
b*a^i(i\in[0,m])
b∗ai(i∈[0,m])
不断增大k,查看
(
a
m
)
k
在
m
a
p
中
是
否
存
在
(a^m)^k在map中是否存在
(am)k在map中是否存在
找到k,同时找到对应的q,所以
x
=
k
m
−
q
x=km-q
x=km−q就出来了
#include<iostream>
#include<map>
#include<cmath>
using namespace std;
typedef long long LL;
map<LL,LL> mp;
LL ksm(LL x,LL n,LL mod)
{
LL ans=1;
while(n){
if(n&1)ans=ans*x%mod;
n>>=1;
x=x*x%mod;
}
return ans;
}
LL bsgs(LL a,LL b,LL p)
{
if(b==1)return 0;//a的0次方等于1
mp.clear();
LL m=sqrt(p);
if(m*m!=p)++m;
LL base=b;
for(int i=0;i<=m;++i){//map存下所有的<b*(a^i),i>
mp[base]=i;
base=base*a%p;
}
LL am=ksm(a,m,p),ans=1;
for(int i=1;i<=m;++i){//查找k与q
ans=ans*am%p;
if(mp[ans])
return i*m-mp[ans];
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
LL a,b,p;
while(cin>>p>>a>>b){
LL ans=bsgs(a,b,p);
if(ans!=-1)cout<<ans<<endl;
else cout<<"no solution"<<endl;
}
return 0;
}
拓展大步小步(exbsgs)
\quad
求
a
x
≡
b
(
m
o
d
p
)
a^x\equiv b(mod \quad p)
ax≡b(modp)中的x(最小非负整数),其中p不一定为素数
化为
a
∗
a
x
−
1
≡
b
(
m
o
d
p
)
a*a^{x-1}\equiv b(mod \quad p)
a∗ax−1≡b(modp)
设g=gcd(a,p),若g不等于1,更新a为a’(a/g),b为b’(b/p),p为p’(p/g),b%p!=0无解,不断重复这个过程,若在此期间a’=b’,答案就是重复次数,因为每重复一次,x’=x-1,直至g=1,然后转化为bsgs求解即可
#include<iostream>
#include<map>
#include<cmath>
using namespace std;
typedef long long LL;
map<LL,LL> mp;
LL ksm(LL x,LL n,LL mod)
{
LL ans=1;
while(n){
if(n&1)ans=ans*x%mod;
n>>=1;
x=x*x%mod;
}
return ans;
}
LL gcd(LL a,LL b)
{
if(!b)return a;
return gcd(b,a%b);
}
LL exbsgs(LL a,LL b,LL p)
{
if(a%p==0)return -1;
if(b==1)return 0;
LL k=0,g,aa=1;
while(1){
g=gcd(a,p);
if(g==1)break;
if(b%g)return -1;
b/=g;
p/=g;
aa=aa*a/g%p;
++k;
if(aa==b)return k;
}
mp.clear();
LL m=sqrt(p);
if(m*m!=p)++m;
LL base=b;
for(int i=0;i<=m;++i){
mp[base]=i;
base=base*a%p;
}
LL am=ksm(a,m,p),ans=aa;
for(int i=1;i<=m;++i){
ans=ans*am%p;
if(mp[ans])
return i*m-mp[ans]+k;
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
LL a,b,p;
while(cin>>a>>p>>b){
if(b>=p){
cout<<"Orz,I can’t find D!"<<endl;
continue;
}
LL ans=exbsgs(a,b,p);
if(ans!=-1)cout<<ans<<endl;
else cout<<"Orz,I can’t find D!"<<endl;
}
return 0;
}