BSGS算法的用途是求方程
ax
a
x
≡
≡
b
b
(mod c)
(
m
o
d
c
)
的最小非负整数解
x
x
若底数与模数
c
c
不互质,则方程无解。
所以我们要判断
if(gcd(a,c)!=1)
{
printf("no solution\n");
continue;
}
我们先求出枚举范围
然后从0到 m m 开始枚举j,用map记录,并允许后面的 j j 覆盖前面的
接下来我们从1到 m m 开始枚举,计算 (am)i(mod c) ( a m ) i ( m o d c ) ,在map中查找,如果与map中的某个值相同我们就计算出 x=i∗m−j x = i ∗ m − j ,退出循环,输出此时的 x x <script type="math/tex" id="MathJax-Element-17">x</script>就是答案
本博客只有BSGS算法的相关操作,证明请看
无敌的ptx的博客
最后附上代码(poj 2417 BSGS模板题)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,c;
map<ll,ll> mp;
ll gcd(ll x,ll y)
{
if(y==0)
return x;
else
return gcd(y,x%y);
}
ll ksm(ll x,ll y,ll mod)
{
ll res=1;
while(y)
{
if(y&1)
res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}
int main()
{
while(~scanf("%lld%lld%lld",&c,&a,&b))
{
mp.clear();
if(gcd(a,c)!=1)
{
printf("no solution\n");
continue;
}
ll m=(ll)ceil(sqrt(c)),ans,pd=0;
for(int j=0;j<=m;++j)//枚举b*a^j存入map
{
if(j==0)
{
ans=b%c;
mp[ans]=j;
continue;
}
ans=(ans*a)%c;
mp[ans]=j;//用后来的覆盖前面的,因为j越大,-j越小
}
ll x=ksm(a,m,c);//先计算a^m,因为之后要计算(a^m)^i
ans=1;
for(int i=1;i<=m;++i)
{
ans=(ans*x)%c;
if(mp[ans])//i越小,求出的x越小(j<=m,但是i每+1,x就要+m)
{
x=i*m-mp[ans];
printf("%lld\n",(x%c+c)%c);
pd=1;
break;
}
}
if(!pd)
printf("no solution\n");
}
return 0;
}