大步小步算法学习笔记

一、BSGS 算法

系统来说,它适用于求离散对数,也就是高次同余方程的解。

给定一个整数 p,以及一个整数 b,一个整数 n,现在要求你计算一个最小的非负整数 l,满足 bln(modp)2b,n<p<231,gcd(p,b)=1

首先,我们发现 l[0,p1],而且所有 i[0,p1],bi 不具有单调性,而且有可能所有 i[0,p1],bi 互不相同。所以有一个朴素做法:计算出所有的 i[0,p1],bi。时间复杂度 O(p),不能通过此题。

考虑用哈希处理。我们将 p 分成若干块。首先我们令 sp,预处理出 b0,b1,,bs1 的所有值,扔进一个哈希表 a 里。然后对于 i[0,p1],一定可以表示为 i=u×s+v,其中 u,v[0,s1],所以 bi=(bs)u×bv。那么我们把所有的 bv 扔进了 a,再枚举 u 的值进行查询就可以了。

map 实现的话,时间复杂度是 O(p×logp),可以通过此题。

map<ll,ll>a;
ll p,b,s,v,w=1,x=1;
int main(){
	p=read();b=read();v=read();
	s=sqrt(p)+1;
	for(ll i=0;i<s;i++){
		if(!a[v])a[v]=i+1;
		v=v*b%p;x=x*b%p;
	}
	for(ll i=1;i<=s;i++){
		w=w*x%p;
		if(a[w]){
			cout<<i*s-a[w]+1<<'\n';
			return 0;
		}
	}
	cout<<"no solution\n";
	return 0;
}

当然更优复杂度是用 gp_hash_table 实现的,时间复杂度 O(p)

#include<ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
gp_hash_table<ll,ll>a;

二、exBSGS 算法

如果 p 不一定与 b 互质怎么办?

那我们努力使得 bln(modp)blp 互质。我们令 g=gcd(b,p),然后我们将 p 反复除以 g,使得 gcd(b,p)=1。假设我们一共除了 cnt 次。如果在除以 g 的过程中得出了结果,直接返回。否则结果一定大于 cnt。然后我们知道如果 ga,gb,gc,那么 ab(modc) 等价于 agbg(modcg)。所以,原问题 bln(modp) 可以转化为 (bg)cnt×blcntngcnt(modpgcnt) 。那么我们发现原问题有解的必要条件之一是 gcnt|n。然后我们得到的式子中,(bg)cnt 是一个整系数,并且 gcd(b,pgcnt)=1,所以可以用 BSGS 求解 lcnt 的最小值。程序里 BSGS 的 a,b,p,c 分别代表 b,(bg)cnt,pgcnt,ngcnt,然后 qwq 代表解,也就是 BSGS 求出来的 lcnt 的最小值,或者 1 代表无解。时间复杂度 O(p)

gp_hash_table<ll,ll>q;
inline ll BSGS(ll a,ll b,ll p,ll c){
	q.clear();
	ll u=1,v=b,w=c,s=sqrt(p)+1;
	for(ll i=0;i<s;i++){
		q[v]=i+1;
		v=v*a%p;u=u*a%p;
	}
	for(ll i=1;i<=s;i++){
		w=w*u%p;
		if(q[w])return i*s-q[w]+1;
	}
	return -1;
}
inline ll exBSGS(ll a,ll b,ll p){
	a%=p;b%=p;
	if(p==1||b==1)return 0;
	ll cnt=0,g,ax=1,qwq;
	while((g=__gcd(a,p))!=1){
		if(b%g)return -1;
		p/=g;cnt++;b/=g;
		ax=ax*(a/g)%p;
		if(ax==b)return cnt;
	}
	return ((qwq=BSGS(a,b,p,ax))==-1)?-1:cnt+qwq;
}

三、例题

  1. P3846 [TJOI2007] 可爱的质数/【模板】BSGS
  2. P4195 【模板】扩展 BSGS/exBSGS
  3. P2485 [SDOI2011]计算器
  4. P3306 [SDOI2013] 随机数生成器
  5. MOD - Power Modulo Inverted
  6. P4454 [CQOI2018]破解D-H协议
  7. [ABC270G] Sequence in mod P
  8. P4884 多少个 1?
  9. P4861 按钮
posted @   lrxQwQ  阅读(40)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示