Title
https://www.luogu.com.cn/problem/P3846
**大意:**给定整数 a , b , p a,b,p a,b,p,其中 a , p a,p a,p互质,求一个非负整数 x x x,使得 a x ≡ b ( m o d p ) a^x\equiv b(mod\ p) ax≡b(mod p)
Solution
Baby Step,Giant Step大步小步算法
设
x
=
i
∗
t
−
j
x=i*t-j
x=i∗t−j,其中
t
=
∣
p
∣
,
0
≤
j
≤
t
−
1
t=|\sqrt p|,0\le j \le t-1
t=∣p∣,0≤j≤t−1,则方程变成
a
i
∗
t
−
j
≡
b
(
m
o
d
p
)
a^{i*t-j}\equiv b(mod\ p)
ai∗t−j≡b(mod p)
对于所有的
j
∈
[
0
,
t
−
1
]
j\in [0,t-1]
j∈[0,t−1],把
b
∗
a
j
m
o
d
p
b*a^j\ mod\ p
b∗aj mod p插入一个
H
a
s
h
Hash
Hash表。
枚举
i
i
i的所有可能取值,即
i
∈
[
0
,
t
]
i\in[0,t]
i∈[0,t],计算出
(
a
t
)
i
m
o
d
p
(a^t)^i\ mod \ p
(at)i mod p,在
H
a
s
h
Hash
Hash表中查找是否存在对应的
j
j
j,更新答案即可。时间复杂度为
O
(
(
p
)
)
O(\sqrt(p))
O((p))
Code
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
inline ll ksm(ll a,ll b,ll p){
ll ans=1;
for(;b;b>>=1,a=(a*a)%p) if (b&1) ans=(ans*a)%p;
return ans;
}
inline ll baby_step_giant_step(ll a,ll b,ll p){
map<ll,ll>hash;
hash.clear();
b%=p;
ll t=(ll)sqrt(p)+1;
for(ll j=0;j<t;j++){
ll val=(long long)b*ksm(a,j,p)%p;
hash[val]=j;
}
a=ksm(a,t,p);
if (a==0) return b==0?1:-1;
for(ll i=0;i<=t;i++){
ll val=ksm(a,i,p);
ll j=hash.find(val)==hash.end()?-1:hash[val];
if (j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}
int main(){
ll a,b,p;
scanf("%lld%lld%lld",&p,&a,&b);
ll ans=baby_step_giant_step(a,b,p);
if (ans!=-1) printf("%lld",ans); else printf("no solution");
}