给定整数 a,b,pa,b,pa,b,p 且 a,pa,pa,p 互质,请求出高次同余方程

ax≡b(modp)a^x\equiv b\pmod pax≡b(modp)

的非负整数解.

首先,

a0≡1(modp)a^0\equiv 1\pmod pa0≡1(modp)

又由欧拉定理知

aφ(p)≡1(modp)a^{\varphi(p)}\equiv 1\pmod paφ(p)≡1(modp)

所以出现了周期.

所以 xxx 在区间 [0,φ(p))[0,\varphi(p))[0,φ(p)) 中一定有,否则就是无解.

那么暴力就是遍历 0∼φ(p)−10\sim \varphi(p)-10∼φ(p)−1 去试每一个,时间复杂度为 O(φ(p))\mathcal{O}(\varphi(p))O(φ(p)).


BabyStep,GiantStep\rm Baby\ Step,Giant\ StepBaby Step,Giant Step,简称 BSGS\rm BSGSBSGS 算法,俗称大步小步算法或拔山盖世.

当 a,pa,pa,p 不互质时就得用 exBSGS\rm exBSGSexBSGS 了.

把 xxx 表示成带余除法的样子:x=it+jx=it+jx=it+j,其中 ttt 是某个整数(取值待会讨论),那么有 0≤i≤⌊φ(p)t⌋,0≤j≤t−10\le i\le\left\lfloor\dfrac{\varphi(p)}{t} \right\rfloor,0\le j\le t-10≤i≤⌊tφ(p)​⌋,0≤j≤t−1.
ax≡b(modp)ait+j≡b(modp)ait≡b⋅a−j(modp)(at)i≡b⋅a−j(modp)a^x\equiv b\pmod p\\ a^{it+j}\equiv b\pmod p\\ a^{it}\equiv b\cdot a^{-j}\pmod p\\ (a^t)^i\equiv b\cdot a^{-j}\pmod p ax≡b(modp)ait+j≡b(modp)ait≡b⋅a−j(modp)(at)i≡b⋅a−j(modp)
BabyStep\rm Baby\ StepBaby Step:∀j∈[0,t−1]\forall j\in [0,t-1]∀j∈[0,t−1],将 (b⋅a−j)modp(b\cdot a^{-j})\bmod p(b⋅a−j)modp 扔进 Hash\rm HashHash 表.

GiantStep\rm Giant\ StepGiant Step:∀i∈[0,⌊φ(p)t⌋]\forall i\in\left[0,\left\lfloor \dfrac{\varphi(p)}{t}\right\rfloor\right]∀i∈[0,⌊tφ(p)​⌋],在 Hash\rm HashHash 表中找是否有 (at)imodp(a^t)^i\bmod p(at)imodp,若有,则 x=it+jx=it+jx=it+j 就是其中一个解.

BabyStep\rm Baby\ StepBaby Step 的时间复杂度为 O(tlog⁡t)\mathcal{O}(t\log t)O(tlogt),GiantStep\rm Giant\ StepGiant Step 的时间复杂度为 O(⌊φ(p)t⌋log⁡t)\mathcal{O}\left(\left\lfloor\dfrac{\varphi(p)}{t} \right\rfloor\log t\right)O(⌊tφ(p)​⌋logt),所以总的时间复杂度就是 O(max⁡(t,⌊φ(p)t⌋)log⁡t)\mathcal{O}\left(\max\left(t,\left\lfloor\dfrac{\varphi(p)}{t} \right\rfloor\right)\log t\right)O(max(t,⌊tφ(p)​⌋)logt),这个很像分块的时间,当取 t=⌊φ(p)⌋t=\left\lfloor\sqrt{\varphi(p)} \right\rfloort=⌊φ(p)​⌋ 时最优.

但是有一个问题,上式右边是 b⋅a−jb\cdot a^{-j}b⋅a−j,导致需要处理逆元,肥肠麻烦.

所以我们改为令 x=it−jx=it-jx=it−j.


x=it−jx=it-jx=it−j,那么有 0≤i≤⌈φ(p)t⌉0\le i\le \left\lceil\dfrac{\varphi(p)}{t}\right\rceil0≤i≤⌈tφ(p)​⌉,0≤j≤t−10\le j\le t-10≤j≤t−1.
ax≡b(modp)ait−j≡b(modp)(at)i≡b⋅aj(modp)a^x\equiv b\pmod p\\ a^{it-j}\equiv b\pmod p\\ (a^t)^i\equiv b\cdot a^j\pmod p ax≡b(modp)ait−j≡b(modp)(at)i≡b⋅aj(modp)
BabyStep\rm Baby\ StepBaby Step:∀j∈[0,t−1]\forall j\in [0,t-1]∀j∈[0,t−1],将 (b⋅aj)modp(b\cdot a^{j})\bmod p(b⋅aj)modp 扔进 Hash\rm HashHash 表.

GiantStep\rm Giant\ StepGiant Step:∀i∈[0,⌈φ(p)t⌉]\forall i\in\left[0,\left\lceil \dfrac{\varphi(p)}{t}\right\rceil\right]∀i∈[0,⌈tφ(p)​⌉],在 Hash\rm HashHash 表中找是否有 (at)imodp(a^t)^i\bmod p(at)imodp,若有且 it−j≥0it-j\ge 0it−j≥0,则 x=it−jx=it-jx=it−j 就是其中一个解.

总的时间复杂度是 O(max⁡(t,⌈φ(p)t⌉)log⁡t)\mathcal{O}\left(\max\left(t,\left\lceil\dfrac{\varphi(p)}{t} \right\rceil\right)\log t\right)O(max(t,⌈tφ(p)​⌉)logt),当取 t=⌈φ(p)⌉t=\left\lceil\sqrt{\varphi(p)} \right\rceilt=⌈φ(p)​⌉ 时最优.

如果用 Hash\rm HashHash 是 O(p)\mathcal{O}(\sqrt{p})O(p​),如果用 map\rm mapmap 是 O(plog⁡p)\mathcal{O}(\sqrt{p}\log\sqrt{p})O(p​logp​).

你会发现它和求单个数逆元一样,时间都只与模数有关,很有意思.

P3846 [TJOI2007] 可爱的质数/【模板】BSGS

对于本题,要求出最小解,因为 0≤j≤t−10\le j\le t-10≤j≤t−1,所以要使 xxx 最小只需使 iii 最小,按顺序遍历,第一次找到就返回.

update:

int val = (ll)b * aj % p;
hash[val] = j;

有可能存在两个 jjj 使得 b⋅ajmodpb\cdot a^j\bmod pb⋅ajmodp 相等,但因为我们是按顺序遍历,所以一定是大的覆盖小的,就会使得 it−jit-jit−j 更小,这正是题目要求的。所以不用担心哈希冲突的问题。

Code\text{Code}Code

注意:在查找时最好不要用

int j = hash[ai] - 1;
if (j >= 0 && i * t - j >= 0)
{return i * t - j;
}

因为在查找不到时会新建一个,导致浪费大量时间.

#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
typedef long long ll;
using namespace std;int phi(int p)
{int ans = p;for (int i = 2; (ll)i * i <= (ll)p; i++){if (p % i == 0){ans = ans / i * (i - 1);while (p % i == 0){p /= i;}}}if (p != 1){ans = ans / p * (p - 1);}return ans;
}int bsgs(int a, int b, int p)
{b %= p;map<int, int> hash;int t = ceil(sqrt(phi(p))), aj = 1;for (int j = 0; j < t; j++){int val = (ll)b * aj % p;hash[val] = j;aj = (ll)aj * a % p;}a = aj;int ai = 1;for (int i = 0; i <= t; i++){if (hash.find(ai) != hash.end()){int j = hash[ai];if (i * t - j >= 0){return i * t - j;}}ai = (ll)ai * a % p;}return -1;
}int main()
{int a, b, p;scanf("%d%d%d", &p, &a, &b);int res = bsgs(a, b, p);if (res == -1){puts("no solution");}else{printf("%d\n", res);}return 0;
}

矩阵 BSGS\rm BSGSBSGS

【BZOJ4128】Matrix

给定矩阵 A,BA,BA,B 和模数 PPP,求最小的 xxx,满足 Ax≡B(modP)A^x\equiv B\pmod PAx≡B(modP).

用矩阵乘法 +++ 矩阵 Hash\rm HashHash 即可

Code\text{Code}Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <cmath>
using namespace std;const int MAXN = 75;
const int BASE = 233;
const int MOD = 19260817;int n, p;struct matrix
{int a[MAXN][MAXN];void init(){memset(a, 0, sizeof(a));}void build(){for (int i = 1; i <= n; i++){a[i][i] = 1;}}matrix operator *(const matrix &x)const{matrix res;res.init();for (int k = 1; k <= n; k++){for (int i = 1; i <= n; i++){if (!a[i][k]){continue;}for (int j = 1; j <= n; j++){res.a[i][j] = (res.a[i][j] + a[i][k] * x.a[k][j]) % p;}}}return res;}int hash(){int ans = 0;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){ans = (ans * BASE + a[i][j]) % MOD;}}return ans;}
};int bsgs(matrix a, matrix b)
{map<int, int> hash;int t = ceil(sqrt(p));matrix aj;aj.init(), aj.build();for (int j = 0; j < t; j++){matrix val = b * aj;hash[val.hash()] = j;aj = aj * a;}a = aj;matrix ai;ai.init(), ai.build();for (int i = 0; i <= t; i++){int x = ai.hash();if (hash.find(x) != hash.end()){int j = hash[x];if (i * t - j >= 0){return i * t - j;}}ai = ai * a;}
}int main()
{scanf("%d%d", &n, &p);matrix a;a.init();for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){scanf("%d", &a.a[i][j]);}}matrix b;b.init();for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){scanf("%d", &b.a[i][j]);}}printf("%d\n", bsgs(a, b));return 0;
}

【数学】Baby Step,Giant Step相关推荐

  1. NOI数学:大步小步(Baby Step Giant Step,BSGS)算法

    BSGS算法求 高次同余方程:1.可爱的质数 2.计算器 BSGS算法求 高次同余方程:1.可爱的质数 2.计算器_啦啦啦32421的博客-CSDN博客 大步小步算法(BSGS)及扩展 & b ...

  2. 离散对数(Baby Step Giant Step)

    现在我来介绍一种算法叫做Baby Step Giant Step.它是用来解决如下方程最小正整数解的     其中 如果,那么我们可以先取模,即,所以在这里我们只讨论的情况. 普通Baby Step ...

  3. BZOJ 2242([SDOI2011]计算器-Baby Step Giant Step第1题)

    2242: [SDOI2011]计算器 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 744  Solved: 289 [Submit][Statu ...

  4. ChatGPT初体验step by step:ChatGPT解决人类提出的数理逻辑问题,Python编程实践

    ChatGPT初体验step by step:ChatGPT解决人类提出的数理逻辑问题,Python编程实践 如果已有有效的open ai的api key,则跳过本文(1)(2)(3)(4),直接从( ...

  5. 【Step By Step】将Dotnet Core部署到Docker下

    一.使用.Net Core构建WebAPI并访问Docker中的Mysql数据库 这个的过程大概与我之前的文章<尝试.Net Core-使用.Net Core + Entity FrameWor ...

  6. python写一个通讯录step by step V3.0

    python写一个通讯录step by step V3.0 更新功能: 数据库进行数据存入和读取操作 字典配合函数调用实现switch功能 其他:函数.字典.模块调用 注意问题: 1.更优美的格式化输 ...

  7. C#2.0实例程序STEP BY STEP--实例二:数据类型

    C#2.0实例程序STEP BY STEP--实例二:数据类型 与其他.NET语言一样,C#支持Common Type Sysem(CTS),其中的数据类型集合不仅包含我们熟悉的基本类型,例如int, ...

  8. 文本分类step by step(二)

    (注:如有转载请标明作者:finallyliuyu, 和出处:博客园) <文本分类 step by step(一)> 在<文本分类step by step(一)>中,我们从处理 ...

  9. 数据库设计Step by Step (9)——ER-to-SQL转化

    2019独角兽企业重金招聘Python工程师标准>>> 引言:前文(数据库设计 Step by Step (8)--视图集成)讨论了如何把局部ER图集成为全局ER图.有了全局ER图后 ...

最新文章

  1. log4j:WARN No such property [datePattern] in org.apache.log4j.RollingFileAppender.
  2. MyBatis 框架系列之基础初识
  3. Ajax系列之JSON数据格式
  4. weex 富文本_Weex richtext 富文本某个字加重显示
  5. mysql排列组合实现_Java实现数列的排列组合
  6. JavaScript:prototype属性使用说明
  7. leetcode 95. Unique Binary Search Trees II | 96. Unique Binary Search Trees
  8. 巧用PHP中__get()魔术方法
  9. 1.Office 365系列(-)
  10. vue 子页面调用父页面的参数_Flutter子组件调用父组件方法修改父组件参数
  11. 服务器内存超限问题_内存超限该怎么办?
  12. 读书记录(持续更新...)
  13. C#高级编程9 第18章 部署
  14. 硬盘测速工具:Blackmagic Disk Speed Test for Mac
  15. c语言小兔子原来有1个萝卜,小兔子和小狐狸的100个睡前晚安小故事
  16. 坚果云android功能,坚果云是什么有什么功能_坚果云相关功能作用介绍_3DM手游
  17. java replaceall 问号_java中替换问号 | 学步园
  18. c语言英语教学大纲,C语言教学大纲(《大学C语言实用教程》)
  19. api 微信内置浏览器js_【微网站开发】之微信内置浏览器API使用
  20. JS 案例 跳水比赛评分系统

热门文章

  1. # 学号12 2016-2017-2 《程序设计与数据结构》第8周学习总结
  2. STM32F103移植uCOS-III
  3. 96分布式电商项目 - 项目部署
  4. 交换机思科远程连接配置
  5. cm-14.1 Android系统启动过程分析(8)-应用程序进程启动过程
  6. av_dump_format
  7. 黑客丛林之旅 第十关
  8. PostgreSQL插入大量数据:pg_testgen插件
  9. [iOS]-Masonry的使用
  10. # 后端开发技巧、常用规范