题意

给定 $a,b$ 和模数 $p$,求整数 $x$ 满足 $a^x \equiv  b(mod \ p)$,不保证 $a,p$ 互质。

(好像是权限题,可见洛谷P4195

分析

之前讲过,可以通过设置 $x = km - r$ 而非 $x = km + r$ 避免求逆元,但是需要逆元存在,$a, p$ 互质的条件保证了这一点。

如果 $a, p$ 不互质怎么办呢?

我们想办法让他们变得互质。

具体地,设 $d_1 = gcd(a, p)$,如果 $d_1 \nmid b$,则原方程无解。否则我们把方程同时除以 $d_1$,得到

$$\frac{a}{d_1}\cdot a^{x-1} \equiv \frac{b}{d_1} \ mod (\frac{p}{d_1})$$

如果 $a$ 和 $\frac{p}{d_1}$ 仍不互质就再除,设 $d_2=gcd(a, \frac{p}{d_1})$。如果 $d2 \nmid \frac{b}{d_1}$,则方程无解;否则同时除以 $d_2$ 得到

$$\frac{a^2}{d_1d_2}\cdot a^{x-2} \equiv \frac{b}{d_1d_2} \ mod(\frac{p}{d_1d_2})$$

这样不停地判断下去,直到 $a \perp \frac{p}{d_1d_2...d_k}$。

记 $D = \prod_{i=1}^kd_i$,于是方程就变成了这样:

$$\frac{a^k}{D}\cdot a^{x-k} \equiv \frac{b}{D} \ mod(\frac{p}{D})$$

由于 $a \perp \frac{p}{D}$,于是推出 $\frac{a^k}{D} \perp \frac{p}{D}$。这样 $\frac{a^k}{D}$ 就有逆元了,于是把它丢到方程的右边,就是一个普通的BSGS问题了,于是求解 $x-k$ 再加上 $k$ 就是原方程的解。

$\frac{a^k}{D}$ 可能很大,事实上可以随手模 $\frac{p}{D}$(显然)。

注意,不排除解小于等于 $k$,所以在消因子之前做 $O(k)$ 枚举,直接验证 $a^i \equiv b\ mod(p)$,就能避免这种情况。

这个复杂度已经有点玄学了,普通的BSGS的复杂度为 $O(\sqrt p logp)$。洛谷上100组,$a, b, p \leq 1e9$,map不开O2优化会超时,需要开O2优化或者使用unordered_map。

代码

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <map>
  4. using namespace std;
  5. typedef long long ll;
  6.  
  7. ll gcd(ll a, ll b)
  8. {
  9. return b ? gcd(b, a%b) : a;
  10. }
  11.  
  12. ll qpow(ll a, ll b, ll p)
  13. {
  14. a = a % p;
  15. ll ret = ;
  16. while(b)
  17. {
  18. if(b&) ret = ret * a % p;
  19. a = a * a %p;
  20. b >>= ;
  21. }
  22. return ret % p;
  23. }
  24.  
  25. ll extend_bsgs(ll a, ll b, ll p) //a^x=b(mod p),a,p不一定互质,不存在返回-1
  26. {
  27. ll _a = a, _b = b, _p = p;
  28. a %= p; b %= p;
  29. if (a == )
  30. return b > ? - : b == && p > ;
  31. ll g, cnt = , q = ;
  32. while ((g = gcd(a, p)) != ) {
  33. if (b == q) return cnt;
  34. if (b % g) return -;
  35. ++cnt;
  36. b /= g;
  37. p /= g;
  38. q = a/g*q%p; //可以随手取模
  39. }
  40.  
  41. ll tmp = ;
  42. for(int i = ;i <= cnt;i++) //枚举小于等于cnt的(好像也不是必须的
  43. {
  44. if(tmp % _p == _b) return i;
  45. tmp = tmp * _a % _p;
  46. }
  47.  
  48. map<ll, ll> x;
  49. ll m = sqrt(p);
  50. for (ll i = , t = b*a%p; i <= m; ++i, t = t*a%p)
  51. x[t] = i;
  52. for (ll i = m, t = qpow(a, m, p); i-m < p-; i += m)
  53. if (q = q*t%p, x.count(q))
  54. return i-x[q]+cnt;
  55. return -;
  56. }
  57.  
  58. int main()
  59. {
  60. ll a, p, b;
  61. while (scanf("%lld %lld %lld", &a, &p, &b), p) {
  62. ll ans = extend_bsgs(a, b, p);
  63. if (ans == -)
  64. puts("No Solution");
  65. else
  66. printf("%lld\n", ans);
  67. }
  68. return ;
  69. }

参考链接:

1. 大步小步算法(BSGS)及扩展  & bzoj2480

2. OI WIKI——BSGS算法

bzoj 2480——扩展BSGS的更多相关文章

  1. bzoj 3283 扩展BSGS + 快速阶乘

    T2  扩展BSGS T3 快速阶乘 给定整数n,质数p和正整数c,求整数s和b,满足n! / pb = s mod pc 考虑每次取出floor(n/p)个p因子,然后将问题转化为子问题. /*** ...

  2. BZOJ 2480 && 3239 && 2995 高次不定方程(高次同余方程)

    链接 BZOJ 2480 虽然是个三倍经验题(2333),但是只有上面这道(BZOJ2480)有 p = 1 的加强数据,推荐大家做这道. 题解 这是一道BSGS(Baby Step Giant St ...

  3. poj 3243 Clever Y && 1467: Pku3243 clever Y【扩展BSGS】

    扩展BSGS的板子 对于gcd(a,p)>1的情况 即扩展BSGS 把式子变成等式的形式: \( a^x+yp=b \) 设 \( g=gcd(a,p) \) 那么两边同时除以g就会变成: \( ...

  4. BSGS与扩展BSGS

    BSGS \(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法 \(BSGS\)算法主要用于解以下同余方程 \[A^x\equiv B(mod\ p)\]其中\(( ...

  5. BSGS&扩展BSGS

    BSGS 给定\(a,b,p\),求\(x\)使得\(a^x\equiv b \pmod p\),或者说明不存在\(x\) 只能求\(\gcd(a,p)=1\)的情况 有一个结论:如果有解则必然存在\ ...

  6. POJ 3243 Clever Y 扩展BSGS

    http://poj.org/problem?id=3243 这道题的输入数据输入后需要将a和b都%p https://blog.csdn.net/zzkksunboy/article/details ...

  7. BSGS和扩展BSGS

    BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map ...

  8. 扩展BSGS求解离散对数问题

    扩展BSGS用于求解axΞb mod(n) 同余方程中gcd(a,n)≠1的情况 基本思路,将原方程转化为a与n互质的情况后再套用普通的BSGS求解即可 const int maxint=((1< ...

  9. bzoj 1467: Pku3243 clever Y 扩展BSGS

    1467: Pku3243 clever Y Time Limit: 4 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description 小 ...

随机推荐

  1. 【Linux】多线程入门详解

    背景知识: 1.每次进程切换,都存在资源的保持和恢复动作,即上下文切换 2.进程的引入虽然可以解决多用户的问题,但是进程频繁切换的开销会严重影响系统性能 3.同一个进程内部有多个线程,这些线程共享的是 ...

  2. 为什么k8s引入pod概念?

    为什么k8s引入pod概念? 1.可管理性 有些容器天生需要紧密关联,以pod为最小单位进行调度 扩展 共享资源 管理生命周期 例如: 一个容器写日志,一个容器读取日志进行相关内容的展示 2.通信和资 ...

  3. CF1016D Vasya And The Matrix

    题目描述 我们有一个 n * m 的矩阵,现在我会告诉你每一行和每一列的异或和请求出任意一种可能的矩阵 数据范围 1<=n,m<=100输入数据确保在int范围内 输入输出格式: 输入格式 ...

  4. hdu 2962 题解

    题目 题意 给出一张图,每条道路有限高,给出车子的起点,终点,最高高度,问在保证高度尽可能高的情况下的最短路,如果不存在输出 $ cannot  reach  destination $ 跟前面 $ ...

  5. linux maven 安装

    1.使用wget命令下载maven安装包 wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.2/binaries/a ...

  6. ADO.NET 一般操作(c#)

    ADO.NET五大对象:SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter .DataSet ,其中SqlDataAdapter 不建议使用 一 ...

  7. win7远程服务器发生身份验证错误,要求的函数不受支持

    远程服务器发生身份验证错误,要求的函数不受支持,远程登录服务器以前都是正常的,今天登录远程桌面就一直是这样的错误.记录一下解决方法. 方法一:卸载补丁KB41037181.打开控制面板,找到“程序和功 ...

  8. idea多级目录不展开的问题

    遇见了一个坑,idea新建的包,和它的上级包重叠在了一起,无法形成树状结构 原因呢,还是因为自己的不细心了,解决方案很简单,下面的是原情况 解决方案,点击左侧栏右上角的设置图表,注意看红框内 把第一行 ...

  9. 解决springboot 新版本 2.1.6 spring-boot-starter-actuator 访问报404

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  10. js加减乘除函数

    经常用到算数的时候,可以直接用:// 除法函数function accDiv(arg1, arg2) { var t1 = 0, t2 = 0, r1, r2; try { t1 = arg1.toS ...