BSGS,全称\(Baby Step Giant Step\),是用于求解离散对数的一种算法。

就是用来求\(A^x \equiv B (mod\ p)\) 的x这么一种算法……

理论知识是:在[0,p)之内是一定有解的,因为指数模的周期性。即\(A^x\)对p的模随x变化有周期性,最大周期不超过p。首先,余数只可能有p个元素,所以x取不超过p个值必定出现相同的余数。根据同余的性质,只要找到两个余数相同的,剩下的全部乘以\(A^k,k\)为整数,所以\(A^n \equiv A^{x+n}\)对于所有x都成立。

朴素算法是枚举0~p-1。

如何改进呢?我们考虑把数分组,每组大小为\(n = \sqrt{p}\),每组\(m = \frac{p}{n}\)个数。

对于每组的询问,我们组内的答案可以看作:\(A^{im-y} \equiv B (mod\ p)\)

移项一下就有:\(A^{im} \equiv BA^y (mod\ p)\)

我们枚举\(0~m-1\),计算所有的\(BA^y\),存进hash表,之后枚举\(1~n\)计算\(A^{im}\)的值,在hash表中找答案即可。

时间复杂度\(O(\sqrt{n})\)

然而这个算法只适用于……\(gcd(A,p) = 1\),即二者互质的情况。否则此时\(A^{-1}\)不存在,就不能把答案看作\(A^{im-y}\)

解决的方法是预先处理成二者互质。

我们一直把方程同除\(A,p\)的公约数就行了。如果中途某一次B除不开就是无解的,否则一直除,得到\(B_n = \frac{A^n}{d_1d_2…d^n}A^{x-n} + p_ny\),令\(D = \frac{A^n}{d_1d_2…d^n}\),此时必存在D的逆元,所以式子变为\(A^{x-n} \equiv B_nD^{-1} (mod\ p_n)\),求解即可。

这有个三合一的板子题。

SDOI2011 计算器

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define I inline using namespace std;
typedef long long ll;
const int M = 200005;
const int mod = 999979; int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
} int T,K,y,z,p; struct Hash
{
int sta[M],top,head[M<<3],num[M],val[M],nxt[M],ecnt;
void init(){ecnt = 0;while(top) head[sta[top--]] = 0;}
void insert(int x,int y)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) {val[i] = y;return;}
if(!head[h]) sta[++top] = h;
nxt[++ecnt] = head[h],head[h] = ecnt;
num[ecnt] = x,val[ecnt] = y;
}
int query(int x)
{
int h = x % mod;
for(int i = head[h];i;i = nxt[i]) if(num[i] == x) return val[i];
return -1;
}
}H; int gcd(int a,int b) {return (!b) ? a : gcd(b,a%b);}
int mul(int a,int b,int t){return 1ll * a * b % t;}
int qpow(int a,int b,int t)
{
int g = 1;
while(b)
{
if(b&1) g = mul(g,a,t);
a = mul(a,a,t),b >>= 1;
}
return g;
} int exgcd(int a,int b,int &x,int &y)
{
if(!b){x = 1,y = 0;return a;}
int d = exgcd(b,a%b,y,x);
y -= a / b * x;
return d;
} int inv(int a,int b)
{
int x,y;
exgcd(a,b,x,y);
return (x % b + b) % b;
} int BSGS(int a,int b,int c)
{
int cnt = 0,G,d = 1;
while((G = gcd(a,c)) != 1)
{
if(b % G) return -1;
cnt++,b /= G,c /= G,d = mul(d,a/G,c);
}
b = mul(b,inv(d,c),c);
H.init();
int s = sqrt(c),p = 1;
rep(i,0,s-1)
{
if(p == b) return i + cnt;
H.insert(mul(p,b,c),i),p = mul(p,a,c);
}
int q = p,t;
for(int i = s;i <= c + s - 2;i += s)
{
t = H.query(q);
if(t != -1) return i - t + cnt;
q = mul(q,p,c);
}
return -1;
} int main()
{
T = read(),K = read();
while(T--)
{
y = read(),z = read(),p = read();
if(K == 1) printf("%d\n",qpow(y,z,p));
if(K == 2)
{
if(z % gcd(y,p)) {printf("Orz, I cannot find x!\n");continue;}
int X,Y;
int d = exgcd(y,p,X,Y);
p /= d;
printf("%d\n",(mul(X,z/d,p) + p) % p);
}
if(K == 3)
{
y %= p,z %= p;
int ans = BSGS(y,z,p);
(ans == -1) ? printf("Orz, I cannot find x!\n") : printf("%d\n",ans);
}
}
return 0;
}

exBSGS算法的更多相关文章

  1. 关于 BSGS 以及 ExBSGS 算法的理解

    BSGS 引入 求解关于\(X\)的方程, \[A^X\equiv B \pmod P \] 其中\(Gcd(A,P)=1\) 求解 我们令\(X=i*\sqrt{P}-j\),其中\(0<=i ...

  2. 『高次同余方程 Baby Step Giant Step算法』

    高次同余方程 一般来说,高次同余方程分\(a^x \equiv b(mod\ p)\)和\(x^a \equiv b(mod\ p)\)两种,其中后者的难度较大,本片博客仅将介绍第一类方程的解决方法. ...

  3. 数论算法 Plus

    好像有不少更新:) 本文主要记录一些不是那么熟悉的高级数论算法的推导与应用. exBSGS算法 解决模数.底数不互质的离散对数问题. (1)为何\(BSGS\)算法不再适用:\(A\)不一定存在逆元, ...

  4. 【BZOJ2242】[SDOI2011] 计算器(数学模板三合一)

    点此看题面 大致题意: 让你完成三种操作:求\(Y^Z\%P\)的值,求满足\(XY\equiv Z(mod\ P)\)的最小非负整数\(X\),求满足\(Y^X\equiv Z(mod\ P)\)的 ...

  5. POJ 3243 Clever Y Extended-Baby-Step-Giant-Step

    题目大意:给定A,B,C,求最小的非负整数x,使A^x==B(%C) 传说中的EXBSGS算法0.0 卡了一天没看懂 最后硬扒各大神犇的代码才略微弄懂点0.0 參考资料: http://quarter ...

  6. 『正睿OI 2019SC Day7』

    简单数论 质因子分解 素性测试 素性测试指的是对一个正整数是否为质数的判定,一般来说,素性测试有两种算法: \(1.\) 试除法,直接尝试枚举因子,时间复杂度\(O(\sqrt n)\). \(2.\ ...

  7. 省选算法学习-BSGS与exBSGS与二次剩余

    前置知识 扩展欧几里得,快速幂 都是很基础的东西 扩展欧几里得 说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象 翡蜀定理 方程$ax+by=gcd(a,b)$ ...

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

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

  9. 「算法笔记」BSGS 与 exBSGS

    一.离散对数 给定 \(a,b,m\),存在一个 \(x\),使得 \(\displaystyle a^x\equiv b\pmod m\) 则称 \(x\) 为 \(b\) 在模 \(m\) 意义下 ...

随机推荐

  1. Smart3D系列教程8之 《模型合并——相邻地区多次建模结果合并》

    迄今为止,Wish3D已经出品推出了7篇系列教程,从倾斜摄影的原理方法.采集照片的技巧.Smart3D各模块的功能应用.小物件的照片重建.大区域的地形重建到DSM及正射影像的处理生产,立足于建模软件的 ...

  2. 线性回归,logistic回归分类

    学习过程 下面是一个典型的机器学习的过程,首先给出一个输入数据,我们的算法会通过一系列的过程得到一个估计的函数,这个函数有能力对没有见过的新数据给出一个新的估计,也被称为构建一个模型.就如同上面的线性 ...

  3. Redis Sentinel 情况下bind地址设置

    Redis Sentinel 情况下bind地址设置 1个master,2个slave,3个sentinel的情况下,注意bind地址的时候不要写0.0.0.0,会导致绑定多个地址, 然后sentin ...

  4. 《UNIX-Shell编程24学时教程》读书笔记Chap1,2 Shell基础,脚本基础

    Chap1 Shell基础 知道该使用哪种命令是依赖于经验的.----惟手熟尔. 1.1 什么是命令 其实知道这些名词好像也没什么帮助,嘻嘻 1.2 什么是Shell 不同用户不同的提示符:不同的环境 ...

  5. Linux上mysql修改密码

    http://www.cnblogs.com/wangjiangze/archive/2011/03/03/1970105.html   MySQL中修改密码及访问限制设置详解

  6. Codeforces 569 B. Inventory

    click here~~ **B. Inventory** time limit per test1 second memory limit per test256 megabytes inputst ...

  7. tensor搭建--windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速

    windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速 原文见于:http://www.jianshu.com/p/c245d46d43f0 ...

  8. 深度解析开发项目之 03 - enum的使用

    深度解析开发项目之 03 - enum的使用 01 - 在#import和@interface之间定义typedef enum 注意: 默认是0,1,2,3 02 - 定义可以操作的数据类型的属性 0 ...

  9. SharePoint ULS Log Viewer 日志查看器

    SharePoint ULS Log Viewer 日志查看器 项目描写叙述 这是一个Windows应用程序,更加轻松方便查看SharePoint ULS日志文件.支持筛选和简单的视图. 信息 这是一 ...

  10. 啥是Restful?

    在Web设计与开发中,经常会看到Restful这个概念.对HTTP没有深入了解的我看到这个,基本一带而过. 其实既然只是概念,理解其中的意思就OK. Restful 1. 一种Web设计/架构方式 2 ...