洛谷 P3846 [TJOI2007]可爱的质数
题意:求一个最小的\(L\),满足\(B^L\equiv N(mod\ P)\)
这就需要用到\(BSGS(Baby\ Step\ Giant\ Step)\)算法了(其实就是个裸的板子题QAQ)
首先要知道\(P\)是质数,所以原式中的\(L\)会在模\(P\)意义下循环,最小解在\([0,P-1]\)
我们设\(L=i\times m-j\),其中\(m=\left \lceil {\sqrt P} \right \rceil\),\(1\le j\le m\),
则方程变为\(B^{i\times m-j}\equiv N(mod\ P)\)
移项得到\((B^{m})^{i}\equiv N\times B^{j}(mod\ P)\)
而\(B,m,n,P\)都是已知的,我们选择哈希,把右边\(N\times 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;
}