BSGS及扩展BSGS算法及例题
\(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算法及例题的更多相关文章
- BSGS与扩展BSGS
BSGS \(BSGS\)算法又称大步小步\((Baby-Step-Giant-Step)\)算法 \(BSGS\)算法主要用于解以下同余方程 \[A^x\equiv B(mod\ p)\]其中\(( ...
- BSGS和扩展BSGS
BSGS: 求合法的\(x\)使得\(a ^ x \quad mod \quad p = b\) 先暴力预处理出\(a^0,a^1,a^2.....a^{\sqrt{p}}\) 然后把这些都存在map ...
- BSGS及扩展BSGS总结(BSGS,map)
蒟蒻哪里有什么总结,只能点击%YL% 还有这位ZigZagK大佬的blog \(\mbox{BSGS}\) 模板题:洛谷P3846 [TJOI2007]可爱的质数 给定\(a,b\)和模数\(\mbo ...
- BSGS及其扩展
目录 定义 原理 朴素算法 数论分块 例题 Luogu2485 [SDOI2011]计算器 题解 代码 扩展 例题 Luogu4195 [模板]exBSGS/Spoj3105 Mod 代码 之前写了一 ...
- BSGS&扩展BSGS
BSGS 给定\(a,b,p\),求\(x\)使得\(a^x\equiv b \pmod p\),或者说明不存在\(x\) 只能求\(\gcd(a,p)=1\)的情况 有一个结论:如果有解则必然存在\ ...
- POJ 3243 Clever Y 扩展BSGS
http://poj.org/problem?id=3243 这道题的输入数据输入后需要将a和b都%p https://blog.csdn.net/zzkksunboy/article/details ...
- bzoj 3283 扩展BSGS + 快速阶乘
T2 扩展BSGS T3 快速阶乘 给定整数n,质数p和正整数c,求整数s和b,满足n! / pb = s mod pc 考虑每次取出floor(n/p)个p因子,然后将问题转化为子问题. /*** ...
- poj 3243 Clever Y && 1467: Pku3243 clever Y【扩展BSGS】
扩展BSGS的板子 对于gcd(a,p)>1的情况 即扩展BSGS 把式子变成等式的形式: \( a^x+yp=b \) 设 \( g=gcd(a,p) \) 那么两边同时除以g就会变成: \( ...
- 扩展BSGS求解离散对数问题
扩展BSGS用于求解axΞb mod(n) 同余方程中gcd(a,n)≠1的情况 基本思路,将原方程转化为a与n互质的情况后再套用普通的BSGS求解即可 const int maxint=((1< ...
随机推荐
- input(type='file')上传多张照片并显示,传到后台
以下内容为网络摘抄和实践修改所得,如有雷同,请谅解!!!! 1.首先是前端页面代码: 其中,<input type="file" id="file_input&qu ...
- 【记录】IntelliJ IDEA—IDEA2018-2019激活
摘要 最智能的java ide [有能力请支持正版] 1.将 0.0.0.0 account.jetbrains.com 和 0.0.0.0 www.jetbrains.com添加到 host ...
- C#ComboBox绑定List
ComboBox绑定List时可能会错, public class Person { public string Name; public int Age; public int Heigth; } ...
- 力扣算法题—079单词搜索【DFS】
给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被重复使用. ...
- 英语词性系列-B02-动词
诗Poem 要求:背诵这首诗,翻译现代文,根据现代文用简单的英文翻译. 动词直观体会 动词 动词 动词 动词 动词 sell卖 buy买 beat击打 look看 dance跳舞 sing唱歌 spe ...
- 【English】20190321
Keep in mind记住[kip ɪn maɪnd] maintenance维护[ˈmentənəns] Also Keep in mind that table maintenance use ...
- java.io.IOException: There appears to be a gap in the edit log. We expected txid ***, but got txid
方式1 原因:namenode元数据被破坏,需要修复解决:恢复一下namenode hadoop namenode -recover 一路选择Y,一般就OK了 方式2 Need to copy the ...
- Nginx 的 access log 如何以 json 形式记录?
Nginx 的 access log 默认是以空格分隔的字符串形式记录的,格式如下 log_format proxy '[$time_local] $remote_addr ' '$protocol ...
- 轻量级卷积神经网络——MobileNet
谷歌论文题目: MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications 其他参考: CNN ...
- ELK的安装
首先得安装好Elasticsearch.Kibana和Logstash(这里全部使用rpm安装的是6.4.2版本,而且都是单机安装,暂时没有考虑分布式安装.) 服务器内存要求至少为4G,下图为运行起来 ...