【[TJOI2007]可爱的质数】

题目

用一道板子题来复习一下\(bsgs\)

\(bsgs\)用于求解形如

\[a^x\equiv b(mod\ p) \]

这样的高次不定方程

由于费马小定理的存在,我们可是直接暴力扫一遍\(p\),由于\(p-1\)次之后肯定会有循环节出现,所以\(O(p)\)时间内就可以出解

\(bsgs\)本质上就是一种分块了

\(m=ceil(\sqrt{p})\),我们设\(x=i\times m-j\)

显然我们只需要\(i,j\in[0,m]\)就可以令\(x\)表示\([0,p]\)之间的所有数

现在我们的方程变成了这个样子

\[\frac{a^{i\times m}}{a^j}\equiv b(mod\ p) \]

也就是

\[a^{i\times m}\equiv b\times a^j(mod\ p) \]

我们可以先开一个\(hash\)表,把所有\(b\times a^j\),其中\(j\in[0,m]\)的值存下来

之后我们挨个检验\(a^{i\times m}\)的值就好了,如果在\(hash\)表里找到和\(a^{i\times m}\)相等的数,那么\(i\times m-j\)就是答案了

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<tr1/unordered_map>
#define re register
#define LL long long
using namespace std::tr1;
unordered_map<LL,LL> ma;
LL a,b,P;
int m;
inline LL quick(LL a,LL b) {LL S=1;while(b) {if(b&1) S=S*a%P;b>>=1;a=a*a%P;}return S;}
int main()
{
	scanf("%lld%lld%lld",&P,&a,&b);
	m=ceil(std::sqrt(P));
	LL S=1,t=quick(a,m);
	for(re int i=0;i<=m;i++) ma[S*b%P]=i%P,S=S*a%P;
	S=t;
	for(re int i=1;i<=m;i++)
	{
		if(ma[S]) {LL ans=i*m-ma[S];printf("%d\n",(ans%P+P)%P);return 0;}	
		S=S*t%P;
	}
	puts("no solution");
	return 0;
}
posted @ 2019-01-04 15:25  asuldb  阅读(261)  评论(0编辑  收藏  举报