2023.1.16 [模板]BSGS/exBSGS

全称Boy Step Girl Step

给定一个质数 p,以及一个整数 a,一个整数 b,现在要求你计算一个最小的非负整数 l,

满足\(a^x \equiv b (mod p)\)

算法流程

设t = \(\lceil \sqrt p \rceil\) ,x = i * t - m (0\(\leq\)i\(\leq\)t , 0\(\leq\)m\(\lt\)t - 1)

\(a^{i * t - b} \equiv b\) (mod p)

\(({a^t})^i \equiv b * a^m\) (mod p)

我们建立一个map,将b * \(a^0\) ~ b * \(a^{t - 1}\) 全部推进去,将值与指数建立映射关系,然后再枚举i,递推算出左式,判断map中是否有值,如果有值则返回答案ans = i * t - map[val]

时间复杂度O(\(\sqrt p\))

inline int BSGS(int a,int b,int p)//a ^ x = b (% p)
{
map <int,int> q;
int t = sqrt(p);
for(int i = 0;i <= t - 1;i++)
q[(1ll * ksm(a,i,p) * b % p)] = i;
int c = ksm(a,t,p);
for(int i = 1;i <= t;i++)
{
int now = ksm(c,i,p);
if(q.find(now) != q.end())
{
int x = q[now];
return i * t - x;
}
}
return -1;
}

exBSGS

那么如果a,p不互质呢?

设d = gcd(a,p);

对于一个同余方程\(a^x \equiv b\) (mod p)

我们可以把它转化成二元一次不定方程的形式 \(a^x\) + py = b

给a分离系数得到 a\(a^{x-1}\) + py = b

想办法消去d,\(\frac ad a^{x-1} + \frac pd y = \frac bd\)

多次迭代,直到d = 1,可以得到以下柿子

\(\frac a{d_1d_2...d_k} a^{x-k} + \frac p{d_1d_2...d_k} y = \frac b{d_1d_2...d_k}\)

转化为原式 \(\frac a{d_1d_2...d_k} a^{x-k} \equiv \frac b{d_1d_2...d_k}\) \(mod (\frac p{d_1d_2...d_k})\)

记录一个变量r = \(\frac a{d_1d_2...d_k} a^{x-k}\),每次迭代时累乘上\(\frac a{d_i}\)

把r移向同余号右侧,那么我们就得到了一个标准的BSGS,但是同余运算中不能左右同除,于是我们用exgcd算出r关于\(\frac p{d_1d_2...d_k}\)的逆元,然后两边同乘以逆元,在跑一边BSGS即可

Code

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
typedef long long ll;
using namespace std;
inline int ksm(ll base,int pts,int mod)
{
ll ans = 1;
for(;pts > 0;pts >>= 1,base = 1ll * base * base % mod)
if(pts & 1)
ans = ans * base % mod;
return ans;
}
inline int BSGS(int a,ll b,int p)//a ^ x = b (% p)
{
__gnu_pbds::gp_hash_table <ll,int> q;
b %= p;
int t = ceil(sqrt(p));
for(int i = 0;i <= t;i++)
q[(ksm(a,i,p) * b % p)] = i;
ll c = ksm(a,t,p),now = 1;
for(int i = 1;i <= t;i++)
{
now = now * c % p;
if(q.find(now) != q.end())
{
int x = q[now];
return (i * t - x + p) % p;
}
}
return -1;
}
inline int exgcd(ll &x,int &y,int a,int b)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int ret = exgcd(x,y,b,a % b);
int k = y;
y = x - (a / b) * y;
x = k;
return ret;
}
inline int gcd(int a,int b)
{
if(b == 0) return a;
return gcd(b,a % b);
}
ll ot = 1;
inline int exBSGS(int a,int b,int p)
{
if(ot == b) return 0;
int x,y;
int d = gcd(a,p);
if(d == 1)
{
ll inv;
exgcd(inv,y,ot,p);
inv = ((inv % p) + p) % p;
return BSGS(a,(1ll * inv * b) % p,p);
}
if(b % d != 0) return -1;
ot = ot * (a / d) % (p / d);
int ret = exBSGS(a,b / d,p / d);
if(ret == -1) return -1;
return ret + 1;
}
signed main()
{
int a,p,b;
scanf("%d%d%d",&a,&p,&b);
while(a || p || b)
{
a %= p;b %= p;
if(b == 1 || p == 1)
{
puts("0");
scanf("%d%d%d",&a,&p,&b);
continue;
}
ot = 1;
int k = exBSGS(a,b,p);
if(k == -1)
printf("No Solution\n");
else
printf("%lld\n",k);
scanf("%d%d%d",&a,&p,&b);
}
return 0;
}

语法tip:

C++中有一种比map 和 unordered_map更快的hash映射gp_hash_table,用法和普通map相同

头文件

#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>

命名空间

using namespace __gnu_pbds

定义hash

(__gnu_pbds::)gp_hash_table <int,int> q;

2023.1.16[模板]BSGS/exBSGS的更多相关文章

  1. 算法笔记--BSGS && exBSGS 模板

    https://www.cnblogs.com/sdzwyq/p/9900650.html 模板: unordered_map<int, int> mp; LL q_pow(LL n, L ...

  2. 【模板】exBSGS/Spoj3105 Mod

    [模板]exBSGS/Spoj3105 Mod 题目描述 已知数\(a,p,b\),求满足\(a^x\equiv b \pmod p\)的最小自然数\(x\). 输入输出格式 输入格式: 每个测试文件 ...

  3. BSGS&EXBSGS 大手拉小手,大步小步走

    大步小步走算法处理这样的问题: A^x = B (mod C) 求满足条件的最小的x(可能无解) 其中,A/B/C都可以是很大的数(long long以内) 先分类考虑一下: 当(A,C)==1 即A ...

  4. BSGS&ExBSGS

    BSGS&ExBSGS 求解形如 \[a^x\equiv b\pmod p\] 的高次同余方程 BSGS 假装\(gcd(a,p)=1\). 设\(m=\lceil\sqrt p \rceil ...

  5. 模板BSGS(SDOI2011计算器) 模板EXBSGS

    BSGS和EXBSGS是OI中用于解决A^xΞB(mod C)的常用算法. 1.BSGS BSGS用于A,C互质的情况. 令m=sqrt(C),此时x可表示为i*m+j. 式中i和j都<=sqr ...

  6. [note]BSGS & exBSGS

    BSGS (感觉这东西还是要写一下) BSGS主要用于求解形如\(x^k=y\pmod p\)(注意这里p与x互质)这样的方程的最小正整数解的问题 设\(m=\lceil\sqrt p\rceil,k ...

  7. Luogu4195 【模板】exBSGS(exBSGS)

    如果a和p互质,用扩欧求逆元就可以直接套用普通BSGS.考虑怎么将其化至这种情况. 注意到当x>=logp时gcd(ax,p)是一个定值,因为这样的话每个存在于a中的质因子,其在ax中的出现次数 ...

  8. LG4195 【模板】exBSGS

    exBSGS 已知数\(a,p,b\),求满足\(a^x≡b\ (\bmod p)\)的最小自然数\(x\). \(100\%\)的数据,\(a,p,b≤10^9\). _皎月半洒花的题解 其实本质上 ...

  9. P4195 【模板】exBSGS/Spoj3105 Mod

    传送门 首先要懂得 $BSGS$,$BSGS$ 可以求出关于 $Y$ 的方程 $X^Y \equiv Z (mod\ mo)$ 的最小解,其中 $gcd(X,Z)=1$ $exBSGS$ 算是 $BS ...

  10. BSGS && EXBSGS

    基础BSGS 用处是什么呢w 大步小步发(Baby-Step-Giant-Step,简称BSGS),可以用来高效求解形如\(A^x≡B(mod C)\)(C为素数)的同余方程. 常用于求解离散对数问题 ...

随机推荐

  1. 【HarmonyOS】【ArkUI】在Service中使用Emitter

    ​ 参考资料 1.相关基础知识:触发器Emitter2.启动服务:ServiceAbility开发 开发步骤 第一步:开发界面,界面内容由一个按钮组件+文本组件构成,然后在按钮组件中添加点击事件,开启 ...

  2. 从 洛谷P5309 Ynoi2011 初始化 看卡常

    一般情况下,程序运行消耗时间主要与时间复杂度有关,超时与否取决于算法是否正确. 但对于某些题目,时间复杂度正确的程序也无法通过,这时我们就需要卡常数,即通过优化一些操作的常数因子减少时间消耗. 比如这 ...

  3. 1.2 Hadoop简介-hadoop-最全最完整的保姆级的java大数据学习资料

    目录 1.2 Hadoop简介 1.2.1 什么是Hadoop 1.2.2 Hadoop的起源 1.2.3 Hadoop的特点 1.2.4 Hadoop的发行版本 1.2.5 Apache Hadoo ...

  4. python安装包出现的两个问题error: Unable to find vcvarsall.bat、提示No module named Crypto.Cipher

    python安装包出现的两个问题 error: Unable to find vcvarsall.bat No module named Crypto.Cipher error: Unable to ...

  5. JavaScript入门⑨-异步编程●异世界之旅

    JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...

  6. MyBatis详解(二)

    前言 本篇幅是继 MyBatis详解(一)的下半部分. MyBatis执行Sql的流程分析 [1]基于前面已经将XML文件进行build解析了并且返回了SqlSessionFactory [1.1]那 ...

  7. hdoj笔记1000

    1000,A+B problem #include <stdio.h>//要用EOF!! int main() { int a,b; while(scanf("%d%d" ...

  8. Nmap常用方法

    1.扫描单个目标地址  在Nmap后面直接添加目标地址即可扫描  nmap 目标地址  2.扫描多个目标地址  如果目标不在同一网段,或在同一网段但不连续且数量不多,可以使用该方法进行扫描  nmap ...

  9. Redis——02 学习

    Redis--02 前面了解了 Redis 以及在 Linux 的安装,下面了解一些 Redis 常用的命令. Redis 常用命令: Redis 是 Key-Value 形式,Key 为字符串类型, ...

  10. week_8

    Andrew Ng 机器学习笔记 ---By Orangestar Week_7_Unsupervised Learning While supervised learning algorithms ...