题意:求一个最小的(L),满足(B^Lequiv N(mod P))
这就需要用到(BSGS(Baby Step Giant Step))算法了(其实就是个裸的板子题QAQ)
首先要知道(P)是质数,所以原式中的(L)会在模(P)意义下循环,最小解在([0,P-1])
我们设(L=i imes m-j),其中(m=left lceil {sqrt P} ight ceil),(1le jle m),
则方程变为(B^{i imes m-j}equiv N(mod P))
移项得到((B^{m})^{i}equiv N imes B^{j}(mod P))
而(B,m,n,P)都是已知的,我们选择哈希,把右边(N imes B^{j}mod P)的值预处理出来丢到(map)里
每次枚举(i),计算出((B^{m})^{i}mod P)的值,如果在(map)里出现,说明原方程成立,计算出来的(L)就是最小解了
有一点要注意的是,如果(B)是(P)的倍数,那么(N)必须也是(P)的倍数,否则无解,这个情况特判下就可以了
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath>
#define int long long
using namespace std;
int p,b,n;
map <int,int> f; //哈希
int mypow(int a,int x,int p) //快速幂
{
int s=1;
while (x)
{
if (x&1)s=s*a%p;
a=a*a%p;
x>>=1;
}
return s;
}
signed main()
{
cin>>p>>b>>n;
if (b%p==0&&n%p!=0)
{
cout<<"no solution"<<endl;
return 0;
}
int m=ceil(sqrt(p)),now=n%p;
for (int i=1;i<=m;i++) //预处理N*B^j mod p
{
now=now*b%p;
if (!f[now])f[now]=i;
}
now=mypow(b,m,p);
int tmp=now; //枚举i
for (int i=1;i<=m;i++)
{
if (f[now])
{
cout<<((i*m-f[now])%p+p)%p<<endl; //防止负数
return 0;
}
now=now*tmp%p;
}
cout<<"no solution"<<endl;
return 0;
}