2023.1.16 [模板]BSGS/exBSGS

全称Boy Step Girl Step

给定一个质数 p,以及一个整数 a,一个整数 b,现在要求你计算一个最小的非负整数 l,

满足\(a^x \equiv b (mod p)\)

算法流程

设t = \(\lceil \sqrt p \rceil\) ,x = i * t - m (0\(\leq\)i\(\leq\)t , 0\(\leq\)m\(\lt\)t - 1)

\(a^{i * t - b} \equiv b\) (mod p)

\(({a^t})^i \equiv b * a^m\) (mod p)

我们建立一个map,将b * \(a^0\) ~ b * \(a^{t - 1}\) 全部推进去,将值与指数建立映射关系,然后再枚举i,递推算出左式,判断map中是否有值,如果有值则返回答案ans = i * t - map[val]

时间复杂度O(\(\sqrt p\))

  1. inline int BSGS(int a,int b,int p)//a ^ x = b (% p)
  2. {
  3. map <int,int> q;
  4. int t = sqrt(p);
  5. for(int i = 0;i <= t - 1;i++)
  6. q[(1ll * ksm(a,i,p) * b % p)] = i;
  7. int c = ksm(a,t,p);
  8. for(int i = 1;i <= t;i++)
  9. {
  10. int now = ksm(c,i,p);
  11. if(q.find(now) != q.end())
  12. {
  13. int x = q[now];
  14. return i * t - x;
  15. }
  16. }
  17. return -1;
  18. }

exBSGS

那么如果a,p不互质呢?

设d = gcd(a,p);

对于一个同余方程\(a^x \equiv b\) (mod p)

我们可以把它转化成二元一次不定方程的形式 \(a^x\) + py = b

给a分离系数得到 a\(a^{x-1}\) + py = b

想办法消去d,\(\frac ad a^{x-1} + \frac pd y = \frac bd\)

多次迭代,直到d = 1,可以得到以下柿子

\(\frac a{d_1d_2...d_k} a^{x-k} + \frac p{d_1d_2...d_k} y = \frac b{d_1d_2...d_k}\)

转化为原式 \(\frac a{d_1d_2...d_k} a^{x-k} \equiv \frac b{d_1d_2...d_k}\) \(mod (\frac p{d_1d_2...d_k})\)

记录一个变量r = \(\frac a{d_1d_2...d_k} a^{x-k}\),每次迭代时累乘上\(\frac a{d_i}\)

把r移向同余号右侧,那么我们就得到了一个标准的BSGS,但是同余运算中不能左右同除,于是我们用exgcd算出r关于\(\frac p{d_1d_2...d_k}\)的逆元,然后两边同乘以逆元,在跑一边BSGS即可

Code

  1. #include<bits/stdc++.h>
  2. #include<ext/pb_ds/assoc_container.hpp>
  3. #include<ext/pb_ds/hash_policy.hpp>
  4. typedef long long ll;
  5. using namespace std;
  6. inline int ksm(ll base,int pts,int mod)
  7. {
  8. ll ans = 1;
  9. for(;pts > 0;pts >>= 1,base = 1ll * base * base % mod)
  10. if(pts & 1)
  11. ans = ans * base % mod;
  12. return ans;
  13. }
  14. inline int BSGS(int a,ll b,int p)//a ^ x = b (% p)
  15. {
  16. __gnu_pbds::gp_hash_table <ll,int> q;
  17. b %= p;
  18. int t = ceil(sqrt(p));
  19. for(int i = 0;i <= t;i++)
  20. q[(ksm(a,i,p) * b % p)] = i;
  21. ll c = ksm(a,t,p),now = 1;
  22. for(int i = 1;i <= t;i++)
  23. {
  24. now = now * c % p;
  25. if(q.find(now) != q.end())
  26. {
  27. int x = q[now];
  28. return (i * t - x + p) % p;
  29. }
  30. }
  31. return -1;
  32. }
  33. inline int exgcd(ll &x,int &y,int a,int b)
  34. {
  35. if(b == 0)
  36. {
  37. x = 1;
  38. y = 0;
  39. return a;
  40. }
  41. int ret = exgcd(x,y,b,a % b);
  42. int k = y;
  43. y = x - (a / b) * y;
  44. x = k;
  45. return ret;
  46. }
  47. inline int gcd(int a,int b)
  48. {
  49. if(b == 0) return a;
  50. return gcd(b,a % b);
  51. }
  52. ll ot = 1;
  53. inline int exBSGS(int a,int b,int p)
  54. {
  55. if(ot == b) return 0;
  56. int x,y;
  57. int d = gcd(a,p);
  58. if(d == 1)
  59. {
  60. ll inv;
  61. exgcd(inv,y,ot,p);
  62. inv = ((inv % p) + p) % p;
  63. return BSGS(a,(1ll * inv * b) % p,p);
  64. }
  65. if(b % d != 0) return -1;
  66. ot = ot * (a / d) % (p / d);
  67. int ret = exBSGS(a,b / d,p / d);
  68. if(ret == -1) return -1;
  69. return ret + 1;
  70. }
  71. signed main()
  72. {
  73. int a,p,b;
  74. scanf("%d%d%d",&a,&p,&b);
  75. while(a || p || b)
  76. {
  77. a %= p;b %= p;
  78. if(b == 1 || p == 1)
  79. {
  80. puts("0");
  81. scanf("%d%d%d",&a,&p,&b);
  82. continue;
  83. }
  84. ot = 1;
  85. int k = exBSGS(a,b,p);
  86. if(k == -1)
  87. printf("No Solution\n");
  88. else
  89. printf("%lld\n",k);
  90. scanf("%d%d%d",&a,&p,&b);
  91. }
  92. return 0;
  93. }

语法tip:

C++中有一种比map 和 unordered_map更快的hash映射gp_hash_table,用法和普通map相同

头文件

  1. #include<ext/pb_ds/assoc_container.hpp>
  2. #include<ext/pb_ds/hash_policy.hpp>

命名空间

  1. using namespace __gnu_pbds

定义hash

  1. (__gnu_pbds::)gp_hash_table <int,int> q;

2023.1.16[模板]BSGS/exBSGS的更多相关文章

  1. 算法笔记--BSGS && exBSGS 模板

    https://www.cnblogs.com/sdzwyq/p/9900650.html 模板: unordered_map<int, int> mp; LL q_pow(LL n, L ...

  2. 【模板】exBSGS/Spoj3105 Mod

    [模板]exBSGS/Spoj3105 Mod 题目描述 已知数\(a,p,b\),求满足\(a^x\equiv b \pmod p\)的最小自然数\(x\). 输入输出格式 输入格式: 每个测试文件 ...

  3. BSGS&EXBSGS 大手拉小手,大步小步走

    大步小步走算法处理这样的问题: A^x = B (mod C) 求满足条件的最小的x(可能无解) 其中,A/B/C都可以是很大的数(long long以内) 先分类考虑一下: 当(A,C)==1 即A ...

  4. BSGS&ExBSGS

    BSGS&ExBSGS 求解形如 \[a^x\equiv b\pmod p\] 的高次同余方程 BSGS 假装\(gcd(a,p)=1\). 设\(m=\lceil\sqrt p \rceil ...

  5. 模板BSGS(SDOI2011计算器) 模板EXBSGS

    BSGS和EXBSGS是OI中用于解决A^xΞB(mod C)的常用算法. 1.BSGS BSGS用于A,C互质的情况. 令m=sqrt(C),此时x可表示为i*m+j. 式中i和j都<=sqr ...

  6. [note]BSGS & exBSGS

    BSGS (感觉这东西还是要写一下) BSGS主要用于求解形如\(x^k=y\pmod p\)(注意这里p与x互质)这样的方程的最小正整数解的问题 设\(m=\lceil\sqrt p\rceil,k ...

  7. Luogu4195 【模板】exBSGS(exBSGS)

    如果a和p互质,用扩欧求逆元就可以直接套用普通BSGS.考虑怎么将其化至这种情况. 注意到当x>=logp时gcd(ax,p)是一个定值,因为这样的话每个存在于a中的质因子,其在ax中的出现次数 ...

  8. LG4195 【模板】exBSGS

    exBSGS 已知数\(a,p,b\),求满足\(a^x≡b\ (\bmod p)\)的最小自然数\(x\). \(100\%\)的数据,\(a,p,b≤10^9\). _皎月半洒花的题解 其实本质上 ...

  9. P4195 【模板】exBSGS/Spoj3105 Mod

    传送门 首先要懂得 $BSGS$,$BSGS$ 可以求出关于 $Y$ 的方程 $X^Y \equiv Z (mod\ mo)$ 的最小解,其中 $gcd(X,Z)=1$ $exBSGS$ 算是 $BS ...

  10. BSGS && EXBSGS

    基础BSGS 用处是什么呢w 大步小步发(Baby-Step-Giant-Step,简称BSGS),可以用来高效求解形如\(A^x≡B(mod C)\)(C为素数)的同余方程. 常用于求解离散对数问题 ...

随机推荐

  1. prefetch和preload

    前面的话 基于VUE的前端小站改造成SSR服务器端渲染后,HTML文档会自动使用preload和prefetch来预加载所需资源,本文将详细介绍preload和prefetch的使用 资源优先级 在介 ...

  2. Springboot结构梳理

    springboot各层关系梳理 1.基本流程 View层-->Controller层(响应用户请求):导入 service层,调用你service方法,controller通过接受前端传来的参 ...

  3. Huawei OJ 题解 - 1. A + B Problem - Go 参考解答

    # Huawei OJ 题解 - 1. A + B Problem - Go 参考解答## 简介- 详情:http://oj.rnd.huawei.com/problems/1/details- 难度 ...

  4. 重学c#系列——动态类型[二十二]

    前言 该系列准备继续完善,一共108篇,持续更新. 正文 为什么有动态类型呢? 是因为很多东西天生就是动态类型的. 比如xml 和 json.cvs.数据库表,这些本来就是数据类型的. 在反射系列中提 ...

  5. Aspose.Cells设置单元格背景色不生效

    Style.BackgroundColor property 获取或设置样式的背景颜色.public Color BackgroundColor { get; set; } 评论 如果要设置单元格的颜 ...

  6. java基础知识-lambda表达式

    一.什么是lambda? 在Java中,我们可以将一个值赋值给一个Java变量. int aValue = 129; String aString = "hello world"; ...

  7. 学习ASP.NET Core Blazor编程系列十三——路由(完)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  8. fbterm的配置,纯文本终端显示中文

    安装 fbterm sudo apt-get install fbterm 设置普通用户可以执行 fbterm 命令 sudo adduser username video #username为用户名 ...

  9. Python异步协程(asyncio详解)

    续上篇讲解yield from博客,上篇链接:https://www.cnblogs.com/Red-Sun/p/16889182.html PS:本博客是个人笔记分享,不需要扫码加群或必须关注什么的 ...

  10. MySQL锁,锁的到底是什么?

    MySQL锁系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊一聊MySQL的锁. 只要学计算机,「锁」永远是一个绕不过的话题.MySQL锁也是一样. 一句话解释MySQL锁: MySQL锁是解决资 ...