BSGS

\(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法

\(BSGS\)算法主要用于解以下同余方程

\[A^x\equiv B(mod\ p)
\]

其中\((A,P)=1\),即\(A\)与\(P\)互质

前置知识

根据欧拉定理\(A^{ \varphi(p)} \equiv1(mod\ p)\),所以\(A^x(mod\ p)\)的循环节为\(\varphi(p)\).也就是说如果上面的方程有解\(x\),那么肯定有\(x \in [0,\varphi(p)]\),所以我们可以枚举一下\(x\)求解

推导

上面是暴力的做法,而\(BSGS\)就是利用分块的思想将上面的算法复杂度优化为\(\sqrt{\varphi(p)}\)(哈希表做法)或者\(\sqrt{\varphi(p)}\ log\;p\)(map)做法

我们令\(m=\lceil \sqrt{\varphi(p)}\rceil\),那么任何一个\(x\in [0,\varphi(p)]\)都可以被表示成\(im-j(i \in [1,m],j\in [0,m])\)的形式

则原式可表示为$$A^{im-j} \equiv B(mod\ p)$$

\[A^{im}\equiv A^jB(mod\ p)
\]

实现

所以先将右边\(A^jB(j \in[0,m])\)预处理出来,存到\(hash\)表中。

然后枚举左边的\(i \in[1,m]\)计算出\(A^{im}\),并在\(hash\)表中查询。

枚举\(i,j\)的复杂度都是\(\sqrt{\varphi(p)}\),常数取决于\(hash\)表

有个细节的地方,一般我们都是要求\(x\)最小的,所以我们希望\(j\)更大,\(i\)更小。所以在往\(hash\)表中存的时候,保留更大的那个\(j\)。从小到大枚举\(i\),遇到可行答案直接输出即可。

例题

luogu3846

代码

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<map>
using namespace std;
typedef long long ll;
#define int ll
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int B,A,L,P;
int qm(int x,int y) {
int ret = 1;
for(;y;y >>= 1,x = 1ll * x * x % P)
if(y & 1) ret = 1ll * x * ret % P;
return ret;
} signed main() {
P = read(),A = read(),B = read();
ma.clear();
int m = ceil(sqrt(P));
int now = B;
for(int i = 0;i <= m;++i) {
ma[now] = i + 1;
now = 1ll * now * A % P;
}
now = 1;
int ans = -1;
int kk = qm(A,m);
for(int i = 1;i <= m;++i) {
now = 1ll * now * kk % P;
if(ma[now]) {
ans =i * m - ma[now] + 1;
break;
}
}
if(ans == -1) puts("no solution");
else printf("%lld\n",ans); return 0;
}

扩展BSGS

\(BSGS\)算法有一定的局限性\((A,p\)互质\()\)。扩展\(BSGS\)可以处理\(A,p\)不互质的情况。

推导

我们已经会了\(A,p\)互质的情况,对于\(A,p\)不互质的情况,只要将转化为\(A,p\)互质即可。

令\(d=gcd(A,p)\)。

如果\(d\nmid B\),那么要么\(B=1\),则答案为\(0\)。否则根据裴蜀定理一定无解。所以我们只要在一开始的时候特判一下\(B=1\)的情况。后面只要发现\(d\nmid B\)就可以说明无解。

所以现在我们假设\(d\mid B\)。

我们将\(A,B,P\)同时除以一个\(d\)。即

\[A^{x-1}\frac{A}{d} \equiv \frac{B}{d}(mod\ \frac{p}{d})
\]

然后重复此操作,直到\(d = 1\)

得到同余方程

\[A^{x-k}\frac{A^k}{\prod\limits_{i=1}^kd_i} \equiv \frac{B}{\prod\limits_{i=1}^kd_i}(mod\ \frac{p}{\prod\limits_{i=1}^kd_i})
\]

设\(p'=\frac{p}{\prod\limits_{i=1}^kd_i},B'=\frac{B}{\prod\limits_{i=1}^kd_i},C=\frac{A^k}{\prod\limits_{i=1}^kd_i},x'=x-k\)

原式就变为$$A^{x'}C\equiv B'(mod\ p')$$

然后就转化为了\(A,p'\)互质的情况,就可以用普通的\(BSGS\)做了。

例题

luogu4195

代码

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<map>
using namespace std;
typedef long long ll;
#define int ll
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int A,B,P;
int gcd(int x,int y) {
return !y ? x : gcd(y,x % y);
}
int qm(int x,int y) {
int ans = 1;
for(;y;y >>= 1,x = 1ll * x * x % P) {
if(y & 1) ans = 1ll * ans * x % P;
}
return ans;
} signed main() {
// freopen("in.in","r",stdin);
while(1) {
ma.clear();
A = read(),P = read(),B = read();
if(!A and !B and !P) return 0;
if(B == 1) {
puts("0");continue;//特判掉b=1的情况
}
int bz = 0,C = 1,d = gcd(A,P),K = 0;
while(d != 1) {
if(B % d) {
puts("No Solution");
bz = 1;break;
}
P /= d;
B /= d;
++K;
C = 1ll * C * (A / d) % P;
d = gcd(A,P);
if(B == C) {
printf("%d\n",K);
bz = 1;
break;
}
}
if(bz == 1) continue;
int m = ceil(sqrt(P));
int now = B;
for(int i = 0;i <= m;++i) {
ma[now] = i + 1;
now = 1ll * now * A % P;
}
now = C;
int ans = -1;
int kk = qm(A,m);
for(int i = 1;i <= m;++i) {
now = 1ll * now * kk % P;
if(ma[now]) {
ans =i * m - ma[now] + 1 + K;
break;
}
}
if(ans == -1) puts("No Solution");
else printf("%lld\n",ans);
} return 0;
}

BSGS与扩展BSGS的更多相关文章

  1. BSGS和扩展BSGS

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

  2. BSGS及扩展BSGS总结(BSGS,map)

    蒟蒻哪里有什么总结,只能点击%YL% 还有这位ZigZagK大佬的blog \(\mbox{BSGS}\) 模板题:洛谷P3846 [TJOI2007]可爱的质数 给定\(a,b\)和模数\(\mbo ...

  3. BSGS及扩展BSGS算法及例题

    \(BSGS(baby-step-giant-step)\)算法是用来解高次同余方程的最小非负整数解的算法,即形如这个的方程: \(a^x\equiv b(mod\ p)\) 其中\(p\)为质数(其 ...

  4. BSGS&扩展BSGS

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

  5. POJ 3243 Clever Y 扩展BSGS

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

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

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

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

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

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

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

  9. BSGS及其扩展

    目录 定义 原理 朴素算法 数论分块 例题 Luogu2485 [SDOI2011]计算器 题解 代码 扩展 例题 Luogu4195 [模板]exBSGS/Spoj3105 Mod 代码 之前写了一 ...

随机推荐

  1. 南京邮电大学java程序设计作业在线编程第七次作业

    王利国的"Java语言程序设计第7次作业(2018)"详细 主页 我的作业列表 作业结果详细 总分:100 选择题得分:60  1. 下列叙述中,错误的是( ). A.Java中, ...

  2. JavaScript中闭包的写法和作用详解

    1.什么是闭包 闭包是有权访问另一个函数作用域的变量的函数. 简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内.而且,这些内部函数可以访问它们所在的外 ...

  3. 彻底删除mysql服务(清理注册表)

    由于安装某个项目的执行文件,提示要卸载MySQL以便它自身MySQL安装,然后我禁用了MYSQL服务,再把这个文件夹删除后,发现还是提示请卸载MYSQL服务. 解决步骤: 1.以管理员身份运行命令提示 ...

  4. 图解slub

    1.前言 在Linux中,伙伴系统(buddy system)是以页为单位管理和分配内存.但是现实的需求却以字节为单位,假如我们需要申请20Bytes,总不能分配一页吧!那岂不是严重浪费内存.那么该如 ...

  5. Burpsuite 之intruder

    首先工具:Burpsuite1.7,DVWA,火狐浏览器代理插件,火狐浏览器,密码字典(以下用Bp代指burpsuite) 启动Bp,启动DVWA,并打开本地代理功能 ​ 开启bp的拦截功能,并在dv ...

  6. [原创]GDB调试指南-断点设置

    前言 上篇<GDB调试指南-启动调试>我们讲到了GDB启动调试的多种方式,分别应用于多种场景.今天我们来介绍一下断点设置的多种方式. 为何要设置断点 在介绍之前,我们首先需要了解,为什么需 ...

  7. python之常用模块

    python 常用模块 之 (subprocess模块.logging模块.re模块) python 常用模块 之 (序列化模块.XML模块.configparse模块.hashlib模块) pyth ...

  8. JAVA—枚举(Enum)学习总结

    1.枚举(Enumeration) 枚举(The Enumeration)接口定义了一种从数据结构中取回连续元素的方式.这种传统接口已被迭代器取代,虽然Enumeration 还未被遗弃,但在现代代码 ...

  9. 2019-04-15 python深浅复制

    原作地址:https://www.cnblogs.com/xueli/p/4952063.html 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,pyth ...

  10. Educational Codeforces Round 62 (Rated for Div. 2) Solution

    最近省队前联考被杭二成七南外什么的吊锤得布星,拿一场Div. 2恢复信心 然后Div.2 Rk3.Div. 1+Div. 2 Rk9,rating大涨200引起舒适 现在的Div. 2都怎么了,最难题 ...