大小步算法 BSGS
前提:
当你遇到一个形如
的问题时,你可能会苦恼。
但是对于条件 为素数且 ,你可能会想到 费马小定理 的 。
所以可以把 分解为 ,这样就可以得出 个 ,然后可以在 中枚举 来求解。
但此时的时间复杂度为 ,通常一个 是一个极大的数,所以并不是很优秀的做法。
大小步算法。
大小步算法(Boby-Step-Giant-Step)也被称为拔山盖世算法、北上广深算法...
如果有人对 分块 或者 筛法 有了解的话,将一个数开方是优秀的复杂度,
那么大小步算法结合这个特点,将 分为了 的形式。
- 设 ,原来的方程就变为了
- 由此我们在方程的两边分别乘上 ,得到
-
既然要找出两个相等的数,何必不用 表来快速查询呢
- 先从 到 枚举 ,将 存入 表中。(Boby-Step)
- 再从 到 枚举 ,将 在 表中查询。(Giant-Step)
-
因为从小到大枚举,所以找到的第一个 ,就是满足 为最小整数解。
代码实现
unordered_map<int,int>vis;
void BSGS()
{
cin >> p >> a >> b;
a %= p; b %= p;
m = ceil(sqrt(p));
am = Pow(a,m,p);
cur = 1;
for (int j = 0; j <= m; ++ j)
{
vis[b*cur%p] = j;
cur = (cur * a) %p;
}
cur = 1;
for (int i = 1; i <= m; ++ i)
{
cur = (cur * am) %p;
if (vis.find(cur) != vis.end())
{
cout << i*m-vis[cur];
return;
}
}
cout << "no solution";
}
再来一遍!
我们的答案皆出自于 这 个数中。
那么将其分为若干组,每个组的大小均设为 。那么相邻的每个组的对应的数之间就会相差 。
- 假如,答案 在第 组中出现了,那么在第 组中就会有 出现。
那么就可以只处理出一组的答案,然后再对所有的 查询(二分、哈希等)即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现