\(BSGS(baby-step-giant-step)\)算法是用来解高次同余方程的最小非负整数解的算法,即形如这个的方程:

$a^x\equiv b(mod\ p)$
其中$p$为质数(其实只要($(a,p)=1$即可)
首先考虑暴力怎么解:由费马小定理可知$a^{p-1}\equiv 1(mod\ p)$,也就是说如果在$[0,p-1]$内无解的话,方程就是无解的。所以我们从小到大枚举$[0,p-1]$中的每一个数,满足方程就结束。但是这里$p-1$并不一定是最小正周期,这个可以由**[阶](https://baike.baidu.com/item/%E9%98%B6/5214104#5)**的定义推出,有兴趣的同学可以去看一下。
但是这个方法在$p$很大时就$GG$啦,于是我们考虑优化一下:
设$x=im-j$,其中$m=\left \lceil \sqrt{p} \right \rceil$。那么我们开始对方程进行变形:
$a^{im}\equiv a^jb(mod\ p)$
显然,$j$是余数,所以有$0\leqslant j \leqslant m-1$,也就是说右边的值最多只有$m$个,而$i$的最大值也只为$m$。所以我们暴力枚举$j$,把$a^jb$存到$map$或哈希表里,再从小到大暴力枚举$i$,每次在哈希表里查一下有没有$a^jb$使得方程成立就可以辣。
同时,有一个很妙的事情:我们枚举$j$时是从小到大枚举的,每次插入到哈希表头的前面,所以表的越靠前的元素的$j$值是越大的,而我们正好想要$j$尽量大,一石二鸟,每次查到一个值就可以直接$return$了。这样查询的近似复杂度就降到$O(1)$了。
要注意先特判一下$x=0$的情况。
板子代码:
``` cpp
namespace Ha { //哈希表
int tot, h[MOD+5], ne[MOD+5];
ll ha[MOD+5];
void insert(ll x, ll num) { //插入操作
ll t = num%MOD;
p[++tot] = x, ha[tot] = num, ne[tot] = h[t], h[t] = tot;
}
ll query(ll tar) { //查询操作
for(int i = h[tar%MOD]; i != -1; i = ne[i])
if(ha[i] == tar) return p[i];
return -1;
}
}
using namespace Ha;
ll bsgs(ll a, ll b, ll p) {
a %= p, b %= p;
if(a == 0 && b != 0) return -1; //a%p==0时显然无解
if(a == 0 && b == 0) return 1;
if(b == 1) return 0;
ll m = ceil(sqrt((double)p)), q = 1, x = 1;
memset(h, -1, sizeof h); //记得清空
for(ll j = 0; j $ta^{x-cnt}\equiv b'(mod\ c')$,其中$a,c'$互质
然后我们就将它转化为标准的$BSGS$可解决的问题啦。
记得特判一下$x\leqslant cnt$的情况(~~为什么留给读者自己思考~~)
粘一下代码:
```cpp
ll bsgs(ll a, ll b, ll p) {
a %= p, b %= p;
if(a == 0 && b != 0) return -1;
if(a == 0 && b == 0) return 1;
if(b == 1) return 0;
ll d = 1, t = 1, cnt = 0, m = ceil(sqrt(p)), q = 1;
while((d = gcd(a, p)) != 1) {
if(b%d) return -1;
cnt++, b /= d, p /= d, t = t*(a/d)%p;
if(b == t) return cnt; //特判
}
memset(h, -1, sizeof h);
for(ll i = 0; i 放一道例题:洛谷/BZOJ。这应该算是板子了吧→_→

AC代码:

#include <bits/stdc++.h>

#define MOD 1000007
#define ll long long int T, k;
ll p[MOD+5]; namespace Ha {
int tot, h[MOD+5], ne[MOD+5];
ll ha[MOD+5];
} using namespace std;
using namespace Ha; void insert(ll x, ll num) {
ll t = num%MOD;
p[++tot] = x, ha[tot] = num, ne[tot] = h[t], h[t] = tot;
} ll query(ll tar) {
for(int i = h[tar%MOD]; i != -1; i = ne[i])
if(ha[i] == tar) return p[i];
return -1;
} ll bsgs(ll a, ll b, ll p) {
a %= p, b %= p;
if(a == 0) return -1;
if(b == 1) return 0;
ll m = ceil(sqrt((double)p)), q = 1, x = 1;
memset(h, -1, sizeof h);
for(ll i = 0; i < m; ++i) insert(i, q*b%p), q = q*a%p;
for(ll i = 1, j; i <= m; ++i) {
x = x*q%p, j = query(x);
if(j != -1) return i*m-j;
}
return -1;
} ll fpow(ll x, ll p, ll mod) {
ll base = x%mod, ret = 1LL;
while(p) {
if(p&1) ret = ret*base%mod;
base = base*base%mod;
p >>= 1;
}
return ret;
} ll inv(ll x, ll p) {
return fpow(x, p-2, p);
} int main() {
cin >> T >> k;
ll x, y, z, inv_y, ans;
while(T--) {
cin >> x >> y >> z;
if(k == 1) cout << fpow(x, y, z) << endl;
else if(k == 2) {
if(x%z == 0) cout << "Orz, I cannot find x!" << endl;
else cout << y*inv(x, z)%z << endl;
}
else {
ans = bsgs(x, y, z);
if(ans == -1) cout << "Orz, I cannot find x!" << endl;
else cout << ans << endl;
}
}
return 0;
}

BSGS及扩展BSGS算法及例题的更多相关文章

  1. BSGS与扩展BSGS

    BSGS \(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法 \(BSGS\)算法主要用于解以下同余方程 \[A^x\equiv B(mod\ p)\]其中\(( ...

  2. BSGS和扩展BSGS

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

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

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

  4. BSGS及其扩展

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

  5. BSGS&扩展BSGS

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

  6. POJ 3243 Clever Y 扩展BSGS

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

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

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

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

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

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

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

随机推荐

  1. <jsp:useBean>、<jsp:setProperty>与<jsp:getProperty>

    <jsp:useBean>标签 会调用java对象的无参构造方法,来创建实例. <jsp:useBean>标签是用来搭配JavaBean元件的标准标签,这里指的JavaBean ...

  2. Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助

    Python第二天  变量  运算符与表达式  input()与raw_input()区别  字符编码  python转义符  字符串格式化  format函数字符串格式化  帮助 目录 Pychar ...

  3. Oracle获取表字段名,字段类型,字段长度,注释

    SELECT b.comments as 注释, a.column_name as 列名, a.data_type || '(' || a.data_length || ')' as 数据类型, a. ...

  4. Linux分页机制之分页机制的实现详解--Linux内存管理(八)

    1 linux的分页机制 1.1 四级分页机制 前面我们提到Linux内核仅使用了较少的分段机制,但是却对分页机制的依赖性很强,其使用一种适合32位和64位结构的通用分页模型,该模型使用四级分页机制, ...

  5. 安装和使用 memcached

    memcached 和 Grails,第 1 部分:安装和使用 memcached 学习 memcached 命令并评估缓存性能 本文是系列文章的第 1 部分,主要介绍 memcached 和 Gra ...

  6. kernel笔记——块I/O

    Linux下,I/O处理的层次可分为4层: 1. 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少  2. 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓 ...

  7. Java 通过地址获取经纬度 - 高德地图

    一.添加依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-v ...

  8. Jenkins pipeline:pipeline 语法详解

    jenkins  pipeline 总体介绍 pipeline 是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化. ...

  9. FM算法解析及Python实现

    1. 什么是FM? FM即Factor Machine,因子分解机. 2. 为什么需要FM? 1.特征组合是许多机器学习建模过程中遇到的问题,如果对特征直接建模,很有可能会忽略掉特征与特征之间的关联信 ...

  10. SpringCloud(2)服务消费者(rest+ribbon)

    1.准备工作 这一篇文章基于上一篇文章的工程.启动eureka-server 工程,端口为 8761.分别以端口 8762 和 8763 启动 service-hi 工程.访问 localhost:8 ...