浅谈BSGS(大步小步)及其扩展
用途:
一般用来求\(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:
#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:
式子转化为:
\]
令\(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:
#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(大步小步)及其扩展的更多相关文章
- 浅谈BSGS
用于求解形如\(a^x≡b\mod p\)的最小非负整数解\(x\). 由欧拉定理\(a^{\phi(p)}≡1\mod p\)可以知道,我们找的解如果有解则一定在\(\phi(p)\)范围内,而最大 ...
- 浅谈BSGS和EXBSGS
我的 BSGS 和各位犇犇的差不多,但是不需要求逆元 Luogu [ TJOI2007 ] 可爱的质数 原题展现 题目描述 给定一个质数 \(p\),以及一个整数 \(b\),一个整数 \(n\),现 ...
- [BSGS]大步小步算法
问题 BSGS被用于求解离散对数,即同余方程: \[ A^x\equiv B\pmod{P} \] 求\(x\)的最小非负整数解. 保证\(A\perp P\)(互质). 分析 首先,我们根据费马小定 ...
- 浅谈集合框架六——集合扩展:Arrays工具类、集合与数组相互转换方式;
最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...
- 浅谈集合框架四——集合扩展:集合循环输出方式及list输出方式的效率对比
最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...
- 离散对数&&大步小步算法及扩展
bsgs algorithm ax≡b(mod n) 大步小步算法,这个算法有一定的局限性,只有当gcd(a,m)=1时才可以用 原理 此处讨论n为素数的时候. ax≡b(mod n)(n为素数) 由 ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC八大类扩展(上篇)
lASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操 ...
- BSGS&EXBSGS 大手拉小手,大步小步走
大步小步走算法处理这样的问题: A^x = B (mod C) 求满足条件的最小的x(可能无解) 其中,A/B/C都可以是很大的数(long long以内) 先分类考虑一下: 当(A,C)==1 即A ...
- [模板]大步小步算法——BSGS算法
大步小步算法用于解决:已知A, B, C,求X使得 A^x = B (mod C) 成立. 我们令x = im - j | m = ceil(sqrt(C)), i = [1, m], j = [0, ...
随机推荐
- Python pymysql对数据库的基础操作
示例数据库名demo,表名info select * from info; 查看该表数据 +----+-------+--------+-----+---------------------+---- ...
- CDH5.X文档
属性参数 https://www.cloudera.com/documentation/enterprise/properties.html
- Python 用户交互程序(day1)
一: 变量 变:变化,重在变字,量:计量,衡量,表示一种状态 变量赋值 : number = 1 变量的规则: 数字,字母,下划线, 任意组合,数字不能开头,python 的关键字不能用,变量名尽量有 ...
- 在子类中,若要调用父类中被覆盖的方法,可以使用super关键字
在子类中,若要调用父类中被覆盖的方法,可以使用super关键字. package text; class Parent { int x; public Parent() { ...
- qDebug的用法
qDebug用于在控制台输出调试信息,主要有以下几种用法. 1.类似c++的cout函数 QString str="world"; qDebug()<<"he ...
- AppCan适配问题
使用AppCan调试中心时,屏幕适配是个问题,经过多次调试总结出如下经验: 1,使用HD+(1560 x 720):显示错乱 2,使用FHD+ (2340 x 1080):显示错乱 3,HD (128 ...
- isinstance与issubclass,反射
目录 isinstance与issubclass isinstance issubclass 反射 定义 反射在模块中的应用 内置方法 isinstance与issubclass isinstance ...
- numpy-tile 数组复制
tile(A, reps):把数组A复制成新数组 # 把 矩阵 看做一个整体,第二个参数代表把 矩阵 复制 m*n 次 b = np.arange(1, 5).reshape(2, 2) print( ...
- Codeforces 1220C. Substring Game in the Lesson
传送门 首先显然的,如果 $l$ 能移动,那么 $r$ 一定可以随便移动,如果 $l$ 不动,那么 $r$ 一定不能动 那么我们现在只要考虑 $l$ 的移动即可 考虑找到位置 $k$ 之前的最左边的最 ...
- lamp项目上线流程简述 (ubuntu16.04 )
1 新建一个sudo用户,而不是直接用root操作 ① 新建用户可参考 https://www.cnblogs.com/bushuwei/p/10880182.html ② 赋予sudo权限: ...