洛谷 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;
}
posted @ 2020-06-08 20:50  eee_hoho  阅读(131)  评论(0编辑  收藏  举报