BSGS
给定一个质数 p p p,以及一个整数 b b b,一个整数 n n n,现在要求你计算一个最小的非负整数 l l l,满足 b l ≡ n b^l\equiv n bl≡n(mod p)
思路
因为
p
p
p为质数,所以可得
a
φ
(
p
)
≡
1
a^{\varphi(p)}\equiv 1
aφ(p)≡1(mod p)
又因为
a
0
≡
1
a^0\equiv 1
a0≡1(mod p);
so,
0
−
φ
(
p
)
0-\varphi(p)
0−φ(p)是一个循环节,不难暴力~
开始:设
x
=
i
m
−
k
,
0
<
=
k
<
=
m
,
m
=
s
q
r
t
(
p
)
x=im-k,0<=k<=m,m=sqrt(p)
x=im−k,0<=k<=m,m=sqrt(p)
方程变为
a
i
m
−
k
≡
b
a^{im-k}\equiv b
aim−k≡b(mod p)
将两边同乘
a
k
a^k
ak 可得
a
i
m
≡
a
k
b
a^{im}\equiv a^kb
aim≡akb(mod p)
于是我们可以分别遍历等式两边的取值,第一次相等时,即可求出最小值
i
m
−
k
im-k
im−k
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll p,b,n,m;
map<int,int> vis;
ll ksm(ll a,ll b,ll p){
ll res=1;
while(b){
if(b&1) res=res*a%p;
b>>=1;a=a*a%p;
}
return res;
}
void work(){
m=ceil(sqrt(p));
for(ll i=0,t=n;i<=m;i++,t=t*b%p) vis[t]=i;
for(ll i=1,tt=ksm(b,m,p),t=tt;i<=m;i++,t=t*tt%p){
if(vis.count(t)){
printf("%lld",i*m-vis[t]);
exit(0);
}
}
puts("no solution");
return;
}
int main(){
scanf("%lld%lld%lld",&p,&b,&n);
work();
return 0;
}
EXBSGS
其实就是不保证a与p互质(
开始搞!!
我们设
g
=
g
c
d
(
a
,
p
)
g=gcd(a,p)
g=gcd(a,p)
原式变为
a
x
g
≡
b
g
\frac{a^x}{g}\equiv \frac{b}{g}
gax≡gb (mod
p
g
\frac{p}{g}
gp)
无解时,b%g!=0&&b!=1(b=1时令x=0)
于是乎 我们还可以得到
a
x
−
1
×
a
g
≡
b
g
a^{x-1}\times\frac{a}{g}\equiv\frac{b}{g}
ax−1×ga≡gb(mod
p
g
\frac{p}{g}
gp)
而
p
g
\frac{p}{g}
gp一定比p小,所以可以一直约到
a
,
p
g
a,\frac{p}{g}
a,gp互质
设
n
a
=
∏
i
k
a
g
i
na=\prod_i^k\frac{a}{g_i}
na=∏ikgia
原式又可以转换为
a
x
−
k
≡
b
∏
i
k
g
×
n
a
a^{x-k}\equiv\frac{b}{\prod_i^k g\times na}
ax−k≡∏ikg×nab(mod
p
∏
i
k
g
\frac{p}{\prod_i^k g}
∏ikgp)
注意:b除以na时需要求逆元
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,p,b,m;
int gcd(int a,int b){return !b ? a : gcd(b,a%b);}
void exgcd(int a,int b,int &x,int &y){
if(!b) x=1,y=0;
else exgcd(b,a%b,y,x),y-=a/b*x;
}
int inv(int a,int b){
int x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
int ksm(int k,int s,int m){
int res=1;
while(s){
if(s&1) res=res*k%m;
s>>=1,k=k*k%m;
}
return res;
}
map<int,int> vis;
int bsgs(int a,int b,int p){
vis.clear();
m=ceil(sqrt(p));b%=p;
for(int i=0,t=b;i<=m;i++,t=t*a%p) vis[t]=i;
for(int i=1,tt=ksm(a,m,p),t=tt;i<=m;i++,t=tt*t%p){
if(vis.count(t)){
return (i*m-vis[t]+p)%p;
}
}
return -1;
}
int exbsgs(int a,int b,int p){
if(b==1||p==1) return 0;
int g=gcd(a,p),k=0,na=1;
while(g>1){
if(b%g!=0) return -1;
k++;b/=g;p/=g;na=na*(a/g)%p;
if(na==b) return k;
g=gcd(a,p);
}
int f=bsgs(a,b*inv(na,p)%p,p);
if(f==-1) return -1;
return f+k;
}
signed main(){
while(scanf("%lld%lld%lld",&a,&p,&b)==3&&a&&p&&b){
a%=p,b%=p;
int ret=exbsgs(a,b,p);
if(ret==-1) puts("No Solution");
else printf("%lld\n",ret);
}
return 0;
}