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. FormData 对象上传二进制文件

    使用jQuery 利用 FormData 上传文件:http://harttle.com/2016/07/04/jquery-file-upload.html     通过FormData对象可以组装 ...

  2. UDK命令

    UDK命令行参数与控制台命令都是大小写不敏感的 命令行  udn中文  udn英文 全词大小写匹配,正则表达式,在c++代码中搜索减号开头的命令行参数(如:-BENCHMARK.-onethread等 ...

  3. reStructuredText文件语法简单学习

    reStructuredText 是一种扩展名为.rst的纯文本文件,通过特定的解释器,能够将文本中的内容输出为特定的格式 1. 章节标题 章节头部由下线(也可有上线)和包含标点的标题组合创建,其中下 ...

  4. SQL SERVER-查询爆破sa密码的主机

    drop table if exists #sql create table #sql ( Logdatae ), processinfo ), [text] varchar(max) ) go IN ...

  5. layui中弹出层的两种表达方式

    方式一: 定义js中定义html变量 方式二: 设置div :hidden:hidden 布局 数据表格自适应大小: 代码: <style> .btn-container { margin ...

  6. java 非访问修饰符 final 的用法

    final 修饰符,用来修饰类.方法和变量 final修饰的类不能被继承 举例,String类是final类,不可以被继承: final修饰的方法不能被重写 只是不能重写,也就是不能被子类修改,但是可 ...

  7. Configuring Apache Kafka for Performance and Resource Management

    Apache Kafka is optimized for small messages. According to benchmarks, the best performance occurs w ...

  8. Ajax概述和判断用户名是否存在的简单代码练习

    在本代码中主要体现,Ajax实现了部分位置的刷新.不需要重新刷新网页,重新请求服务器.下面用过代码来对Ajax更深的认识 这里需要创建,一个jsp文件(显示登录界面),js文件(对Ajax的主要设置) ...

  9. 微信小程序支付,带java源码

    先说下这个的背景吧... 本人是做java后端的,自认为还有很大的发展空间(嘻嘻,你懂的),看过一段时间的小程序可是没有支付成功...最近公司要做小程序项目,老大让我看下小程序,折腾了好几天,参照着h ...

  10. Linux-基础学习(一)-基本命令

    开始今日份整理 1.Linux的文件目录操作 1.1 ls 简述:ls是list的缩写,用于列出指定目录或文件 常用的选项 1 -a:显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为隐藏, ...