1.引入
BSGS算法又名拔山盖世算法,也叫北上广深算法,也叫大步小步算法,总之就是名字很多了,但是实际上他就是一个解决同余方程 给定a,b,p,求最小的非负整数x,满足 ax ≡ b(mod p)。
2.过程
先令 x = i*m-j,其中 m=ceil(sqrt(p)),ceil是向上取整。
这样原式就变为 ai*m-j = b (mod p),
移项就变成了 ai*m = b*aj (mod p)
枚举j (范围0-m) ,将 b*aj 存入hash表。
枚举i (范围1-m) ,从hash表中寻找第一个满足ai*m = b*aj (mod p)。
此时 x = i*m-j 就是所要求的。
3.原因:
先令 x = i*m-j,其中 m=ceil(sqrt(p)),ceil是向上取整。
这样原式就变为 ai*m-j = b (mod p),
移项就变成了 ai*m = b*aj (mod p)
枚举j (范围0-m) ,将 b*aj 存入hash表。
枚举i (范围1-m) ,从hash表中寻找第一个满足ai*m = b*aj (mod p)。
此时 x = i*m-j 就是所要求的。
模板
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define ll long long
using namespace std;
map<ll,int> mp;
ll pow(ll a,ll b,ll mod)
{
ll ans=1;
for(;b>0;b/=2)
{
if(b%2==1)
ans=(ans*a)%mod;
a=a*a%mod;
}
return ans;
}
int main()
{
ll a,b,c;
mp.clear();
while(scanf("%lld%lld%lld",&c,&a,&b)!=EOF)
{
if(a%c==0)
{
printf("No solution\n");
continue;
}
int flag=0;
ll m=ceil(sqrt(c));
ll ans;
for(int i=0;i<=m;i++)
{
if(i==0)
{
ans=b%c;
mp[ans]=i;
continue;
}
ans=(ans*a)%c;
mp[ans]=i;
}
ll cur=pow(a,m,c);
ans=1;
for(int i=0;i<=m;i++)
{
ans=(ans*cur)%c;
if(mp[ans])
{
int t=i*m-mp[ans];
printf("%d\n",(t%c+c)%c);
flag=1;
break;
}
}
if (!flag)
printf("no solution\n");
}
return 0;
}