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. Spring 事务与脏读、不可重复读、幻读

    索引: 目录索引 参看代码 GitHub: 1.Spring 事务 2.事务行为 一.Spring 事务: Spring 的事务机制是用统一的机制来处理不同数据访问技术的事务处理. Spring 的事 ...

  2. 什么是tomcat集群?

    什么是tomcat集群? 利用nginx对请求进行分流,将请求分配给不同的tomcat去处理,减少每个tomcat的负载量,提高服务器的响应速度. 目标 实现高性能负载均衡的tomcat集群. 工具 ...

  3. Ubuntu18.04 安装jdk1.8

    1.oracle官网下载压缩包,点击链接. 2.解压 1 tar -zxvf jdk-8u171-linux-x64.tar.gz 3.移动到制定目录 ##将文件从下载目录 挪到/usr/local下 ...

  4. Postman安装及入门教程

    安装 本文只是基于 Chrome 浏览器的扩展插件来进行的安装,并非单独应用程序. 首先,你要台电脑,其次,安装有 Chrome 浏览器,那你接着往下看吧. 1. 官网安装(别看) 打开官网,http ...

  5. C#基础知识之关键字

    关键字是 C# 编译器预定义的保留字.这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀.在 C# 中,有些关键字在代码的上下文中有特殊的意义,如 ...

  6. centos7下kubernetes(11。kubernetes-运行一次性任务)

    容器按照持续运行的时间可以分为两类:服务类容器和工作类容器 服务类容器:持续提供服务 工作类容器:一次性任务,处理完后容器就退出 Deployment,replicaset和daemonset都用于管 ...

  7. Android开发欢迎页点击跳过倒计时进入主页

    没点击跳过自然进入主页,点击跳过之后立即进入主页     1.欢迎页布局activity_sp.xml放一张背景图(图片随你便啦)再放一个盛放倒计时的TextView   <?xml versi ...

  8. 压力测试Apache

    在做类似商城秒杀系统的同事都知道要在支持高并发,高可用的环境下进行多次的压力测试来防止自己的项目结构被高额的点击量击穿,导致商品超卖等损失 介绍一款简单的软件 xampp xam里带了Apache服务 ...

  9. C# 使用微软自带的Speech进行语音输出

    1.在VS中使用微软自带的Speech进行语音播报,首先需要添加引用: 2.具体实现逻辑代码如下:

  10. JS&Java实现常见算法面试题

    Github上的算法repo地址:https://github.com/qcer/Algo-Practice (如果你觉得有帮助,可以给颗星星收藏之~~~) 一.Java实现部分 参见随笔分类的算法部 ...