用途:

一般用来求\(a^x\equiv b\,\,(mod\,p)\)的最小正整数解,其中gcd(a,p)=1

设\(u=\lceil sqrt(p)\rceil\),则式子可以转化为\(a^{iu-j}\equiv b\,\,(mod\,p)\),其中\(i\in[1,u],j\in[0,u)\)

于是\(a^{iu}\equiv a^jb\,\,(mod\,p)\),我们就可以枚举j,存到map中,再枚举i判重就行了

不过当存在不同的j使\(a^jb\,mod\,p\)相同时,我们记录较大的(因为j越大答案越小嘛)

简易原理:

费马小定理:若gcd(x,p)=1,则有\(\\x^{p-1}\equiv1\,\,(mod\,p)\),得到\(x^p\equiv x\,\,(mod\,p)\)

所以当指数不小于p时,mod p的值会形成循环

Code:

板子题:luogu P4028 New Product

#include<bits/stdc++.h>
#define ll long long
using namespace std;
map<int,int> mp;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int quickpow(int a,int b,int p){
int re=1;
while(b){if(b&1) re=1ll*re*a%p;a=1ll*a*a%p;b>>=1;}
return re;
}
void solve(){
int p=read(),a=read(),b=read();
if(a%p==0){puts("Couldn't Produce!");return ;}
if(b==1){puts("0");return ;}
int u=sqrt(p)+1,v=b;mp.clear();
for(int i=0;i<u;i++)
mp[v]=i,v=1ll*v*a%p;
int w=quickpow(a,u,p);v=1;
for(int i=1;i<=u;i++){v=1ll*v*w%p;
if(mp.count(v)){
printf("%d\n",i*u-mp[v]);
return ;
}
}puts("Couldn't Produce!");
}
int main(){
int T=read();
while(T--) solve();
return 0;
}

扩展:

可以看到BSGS是有着局限性的,即必须满足gcd(a,p)=1

那么当gcd(a,p)!=1时呢?我们设\(d=gcd(a,p)\)

Step1:

​ 我们首先判断\(b\)是否满足\(d|b\),若不满足,由裴蜀定理可知无解

Step2:

​ 式子转化为:

\[a^{x-k}\frac{a^k}{\Pi_{i=1}^kd_i}\equiv \frac{b}{\Pi_{i=1}^kd_i}\,\,(mod\,\,\frac{p}{\Pi_{i=1}^kd_i})
\]

​ 令\(c=\frac{a^k}{\Pi_{i=1}^kd_i},b'=\frac{b}{\Pi_{i=1}^kd_i},p‘=\frac{p}{\Pi_{i=1}^kd_i}\),若\(c=b'\),则直接输出\(k\)

Step3:

​ 令\(d=gcd(a,p')\),若\(d\ne 1\),则返回step1,不过b变成了b'

全部完成后,我们得到式子:\(a^{x-k}c\equiv b'\,\,(mod\,\,p')\),此时满足\(gcd(a,p')=1\)

那么我们便可以直接BSGS了

Code:

板子题:luogu P4195 exBSGS

#include<bits/stdc++.h>
#include<unordered_map>
#define ll long long
using namespace std;
unordered_map<int,int> mp;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
inline int gcd(int x,int y){
if(y>x) swap(x,y);
while(y){swap(x,y);y=y%x;}
return x;
}
inline int quickpow(int a,int b,int p){
int re=1;
while(b){if(b&1) re=1ll*re*a%p;a=1ll*a*a%p;b>>=1;}
return re;
}
inline void solve(int a,int p,int b){
if(p==1){puts("0");return ;}
if(b==1){puts("0");return ;}
int d=gcd(a,p),flag=0,k=0,c=1;
while(d^1){
if(b%d){
puts("No Solution");
flag=1;break;
}p/=d,b/=d,++k;
c=1ll*c*(a/d)%p;
if(b==c){
printf("%d\n",k);
flag=1;break;
}d=gcd(a,p);
}if(flag) return ;
mp.clear();
int u=sqrt(p)+1,v=b;
for(int i=0;i<u;i++)
mp[v]=i,v=1ll*v*a%p;
v=c,c=quickpow(a,u,p);
for(int i=1;i<=u;i++){
v=1ll*v*c%p;
if(mp.count(v)){
printf("%d\n",i*u-mp[v]+k);
return ;
}
}puts("No Solution");
}
int main(){
while(1){
int a=read(),p=read(),b=read();
if(a==0&&b==0&&p==0) return 0;
a%=p;b%=p;solve(a,p,b);
}
}

话说为什么unordered_map比map快这么多啊,不过有时候编译会出锅...

浅谈BSGS(大步小步)及其扩展的更多相关文章

  1. 浅谈BSGS

    用于求解形如\(a^x≡b\mod p\)的最小非负整数解\(x\). 由欧拉定理\(a^{\phi(p)}≡1\mod p\)可以知道,我们找的解如果有解则一定在\(\phi(p)\)范围内,而最大 ...

  2. 浅谈BSGS和EXBSGS

    我的 BSGS 和各位犇犇的差不多,但是不需要求逆元 Luogu [ TJOI2007 ] 可爱的质数 原题展现 题目描述 给定一个质数 \(p\),以及一个整数 \(b\),一个整数 \(n\),现 ...

  3. [BSGS]大步小步算法

    问题 BSGS被用于求解离散对数,即同余方程: \[ A^x\equiv B\pmod{P} \] 求\(x\)的最小非负整数解. 保证\(A\perp P\)(互质). 分析 首先,我们根据费马小定 ...

  4. 浅谈集合框架六——集合扩展:Arrays工具类、集合与数组相互转换方式;

    最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...

  5. 浅谈集合框架四——集合扩展:集合循环输出方式及list输出方式的效率对比

    最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...

  6. 离散对数&&大步小步算法及扩展

    bsgs algorithm ax≡b(mod n) 大步小步算法,这个算法有一定的局限性,只有当gcd(a,m)=1时才可以用 原理 此处讨论n为素数的时候. ax≡b(mod n)(n为素数) 由 ...

  7. 【ASP.NET MVC系列】浅谈ASP.NET MVC八大类扩展(上篇)

    lASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操 ...

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

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

  9. [模板]大步小步算法——BSGS算法

    大步小步算法用于解决:已知A, B, C,求X使得 A^x = B (mod C) 成立. 我们令x = im - j | m = ceil(sqrt(C)), i = [1, m], j = [0, ...

随机推荐

  1. mysql——单表查询——分组查询——示例

    一.基本查询语句 select的基本语法格式如下: select 属性列表 from 表名和视图列表 [ where 条件表达式1 ] [ group by 属性名1 [ having 条件表达式2 ...

  2. java 换包

    1.进入目录:cd /opt/cw_isc/ 2.查看:ls 3.查看进程:ps -ef|grep aw-sc-package-all.jar 4.杀死进程kill -9 3982 5.查看进程:ps ...

  3. session 的理解

  4. python 并发编程 多线程 GIL全局解释器锁基本概念

    首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码. ...

  5. Win10 开启 热点的简单办法

  6. Linux进程后台执行nohup(OpenTSDB后台运行方法)

    1.问题描述 OpenTSDB执行./tsdb tsd启动之后,占有控制台执行并且Ctrl+C后就退出了,关闭控制台同样会退出. 2.解决方法(在/opt/module/opentsdb-2.3.1/ ...

  7. 洛谷 - P3225 - 矿场搭建 - 双连通分量

    https://www.luogu.org/problem/P3225 这个东西有点绕. 最平凡的情况,整个原图只有一个点,那么它坍塌了之后就没有点了,不需要进行任何逃生.否则,当一个点坍塌之后,每个 ...

  8. HTML-复杂动画和变形

    1.复杂动画 (1)涉及到的属性: animation-name:动画名称: animation-duration:单次动画总时长: animation-timing-function:时间函数: a ...

  9. echarts 给legend图例加个标题式文字设置为普通文本不可点击

    legend: [ { orient: "horizontal", // 'vertical' x: "68%", // 'center' | 'left' | ...

  10. RabbitMQ从安装到使用

    一.在Linux中安装RabbitMQ 通过Docker安装: 获取镜像(选用management是带有管理界面的) docker pull rabbitmq:-management 查看下载好的镜像 ...