大步小步()

大步小步算法是一种可以在\(O(\sqrt{p})\)的时间内求出形如 \(a^x \equiv b \pmod{p}\)或 \(x^a \equiv b \pmod{p}\)的算法,其实思想异常的简单,这里介绍一下第一种

我们发现,$a^{\phi(p)} $ ~ \(a^{1}\) 之间的结果包含了所有的可能模数结果,所以我们通过人类智慧进行根号平衡

我们设 \(q=\sqrt{p}+1\),则发现,所有小于根号的结果我们可以直接爆算,所有大于根号的结果我们可以像分块那样预处理出来

所以大步小步其实就是数论意义上的分块?

说一下具体算法流程

我们先暴力预处理一下零散块的答案,然后把他挪到柿子右边,像这样

(这里设总块数为 \(i\),零散块为 \(j\),块长为 \(t\)

这一步变形的前提是 \(a\) 与 \(p\) 互质,才能推出来这一步,否则,要用到

EX-BSGS

接下来的事情好办了,我们对于每一个 \(j\) 预处理出来 \(a^j \, * \, b \pmod p\),然后枚举大块的块数,验证一下就好了

复杂度 \(O(\sqrt{p})\)

#include <iostream>
#include <map> 
#define ll long long


using namespace std;
ll a,b,p;
map<ll,ll>hsh;

void bsgs(){
	ll t;
	for(t=1;t*t<=p;++t) ;
	--t;
	ll tmp=1;
	hsh[0]=b;
	for(int i=1;i<t;++i)
		tmp=(tmp*a)%p,hsh[(b*tmp)%p]=i;
	if(a==0){
		if(b==0) cout << 1  << endl;
		else cout << "no solution" << endl;
		return ;
	} 
	tmp=(tmp*a)%p;
	ll q=1;
	for(int i=1;i<=t;++i){
		q=(tmp*q)%p;
		if(hsh.find(q)!=hsh.end()) {
			cout << i*t-hsh[q] << endl;
			return ;
		}
	}
	cout << "no solution" << endl;
		
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	cin >> p >> a >> b;
	bsgs();
	
	return 0;
} 

————————

大步小步算法是一种可以在\(O(\sqrt{p})\)的时间内求出形如 \(a^x \equiv b \pmod{p}\)或 \(x^a \equiv b \pmod{p}\)的算法,其实思想异常的简单,这里介绍一下第一种

我们发现,$a^{\phi(p)} $ ~ \(a^{1}\) 之间的结果包含了所有的可能模数结果,所以我们通过人类智慧进行根号平衡

我们设 \(q=\sqrt{p}+1\),则发现,所有小于根号的结果我们可以直接爆算,所有大于根号的结果我们可以像分块那样预处理出来

所以大步小步其实就是数论意义上的分块?

说一下具体算法流程

我们先暴力预处理一下零散块的答案,然后把他挪到柿子右边,像这样

(这里设总块数为 \(i\),零散块为 \(j\),块长为 \(t\)

这一步变形的前提是 \(a\) 与 \(p\) 互质,才能推出来这一步,否则,要用到

EX-BSGS

接下来的事情好办了,我们对于每一个 \(j\) 预处理出来 \(a^j \, * \, b \pmod p\),然后枚举大块的块数,验证一下就好了

复杂度 \(O(\sqrt{p})\)

#include <iostream>
#include <map> 
#define ll long long


using namespace std;
ll a,b,p;
map<ll,ll>hsh;

void bsgs(){
	ll t;
	for(t=1;t*t<=p;++t) ;
	--t;
	ll tmp=1;
	hsh[0]=b;
	for(int i=1;i<t;++i)
		tmp=(tmp*a)%p,hsh[(b*tmp)%p]=i;
	if(a==0){
		if(b==0) cout << 1  << endl;
		else cout << "no solution" << endl;
		return ;
	} 
	tmp=(tmp*a)%p;
	ll q=1;
	for(int i=1;i<=t;++i){
		q=(tmp*q)%p;
		if(hsh.find(q)!=hsh.end()) {
			cout << i*t-hsh[q] << endl;
			return ;
		}
	}
	cout << "no solution" << endl;
		
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0); 
	cin >> p >> a >> b;
	bsgs();
	
	return 0;
}