\(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. ext遍历表单中所有输入项,并全部设置为只读

    baseInfoForm.getForm().getFields().each(function (field) { // 设置只读 field.setReadOnly(true); })

  2. 【原】Java学习笔记006 - 流程控制

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 需求:写一万次&q ...

  3. Node+express实现后台服务接口

    一.准备工作 创建代码目录,依次执行以下操作 1.(若没有安装过)安装node 2.npm init(package.json) 3.安装express(请求)npm install express ...

  4. js前端导出Excel表格后数字自动变成科学计数法问题

    一般的文件导出都是后端进行导出,最近一个项目遇到导出接口挂掉了,前端实现导出的情况. 背景是vue框架,iView组件.可以直接使用exportCsv方法进行导出. 导出时进行一下行和列的切割就可以了 ...

  5. Linux(CentOS)下设置nginx开机自动启动(2个办法)

    首先,在linux系统的/etc/init.d/目录下创建nginx文件,使用如下命令: vim /etc/init.d/nginx 在脚本中添加如下命令: #!/bin/sh # # nginx - ...

  6. WiFi广告强推的基本技术原理和一些相关问题

    WiFi推原理(转) 本文地址:http://jb.tongxinmao.com/Article/Detail/id/412 WiFi广告强推的基本技术原理和一些相关问题 WiFi广告推送原理就是利用 ...

  7. vim美化基本配置

    在home目录中创建一个 .vimrc文件 vim ~/.vimrc 文件基本配置 " 设置当文件被改动时自动载入 set autoread " quickfix模式 autocm ...

  8. firewall centos

    firewall-cmd --add-port=8056/tcp    --临时增加端口 firewall-cmd --permanent --zone=public --add-port=6069/ ...

  9. 洛谷 P1908 逆序对

    \[传送门qwq\] 题目描述 猫猫\(TOM\)和小老鼠\(JERRY\)最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计. 最近,\(TOM\)老猫查阅 ...

  10. 2-STM32带你入坑系列(点亮一个灯--Keil)

    1-STM32带你入坑系列(STM32介绍) 首先是安装软件 这一节用Kei来实现,需要安装MDK4.7这个软件,怎么安装,自己百度哈.都学习32的人了,不会连个软件都不会安装吧....还是那句话 没 ...