版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/80583859
BSGS算法的用途是求方程
的最小非负整数解
若底数
与模数
不互质,则方程无解。
所以我们要判断
if(gcd(a,c)!=1)
{
printf("no solution\n");
continue;
}
我们先求出枚举范围
然后从0到 开始枚举j,用map记录 ,并允许后面的 覆盖前面的
接下来我们从1到 开始枚举 ,计算 ,在map中查找,如果与map中的某个值相同我们就计算出 ,退出循环,输出此时的 就是答案
本博客只有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;
}