bsgs(求解高次同余方程)学习笔记

基础篇

BSGS(baby-step giant-step),即大步小步算法。常用于求解离散对数问题。形式化地说,该算法可以在 O ( p ) O(\sqrt{p}) O(p ) 的时间内求解

a x ≡ b ( m o d p ) a^x \equiv b \pmod p axb(modp)

其中 a ⊥ p a\perp p ap。方程的解 x x x 满足 0 ≤ x < p 0 \le x < p 0x<p。(在这里需要注意,只要 a ⊥ p a\perp p ap 就行了,不要求 p p p 是素数)

例题:3846 [TJOI2007] 可爱的质数/【模板】BSGS
求解过程
要求 a x ≡ b ( m o d p ) a^x \equiv b \pmod p axb(modp)
首先令 x = i m − j x=im-j x=imj
化为 ( a m ) i ≡ b ∗ a j ( m o d p ) (a^m)^i \equiv b*a^j\pmod p (am)ibaj(modp)
j的取值范围是 [ 0 , m ) [0,m) [0,m),先枚举等号右边,并存入hash表中
i的取值范围是 [ 1 , m ] [1,m] [1,m],枚举等号左边,同时在hash表中查找是否有对应的值,找到的第一个为最小
在这里插入图片描述

#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
template<class...Args>
void debug(Args... args) {//Parameter pack
	auto tmp = { (cout << args << ' ', 0)... };
	cout << "\n";
}
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
const ll N = 1e5 + 5;
const ll INF = 0x7fffffff;
const ll MOD = 1e9 + 7;
ll qpow(ll x, ll n, ll mod) {
	ll ans = 1;
	while (n) {
		if (n & 1)ans = (ans * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return ans % mod;
}
ll bsgs(ll a, ll b, ll p) {
	if (b == 1) return 0;
	ll m = ceil(sqrt(p));//时间复杂度为O(sqrt(n))
	ll t = b;
	unordered_map<ll, ll> dict;
	dict[b] = 0;
	for (int j = 1; j < m; ++j) {//计算b*aj对应的值将对应的j值存入hash表中
		t = t * a % p;
		dict[t] = j;
	}
	ll mi = qpow(a, m, p);//计算a^m
	t = 1;
	for (int i = 1; i <= m; ++i) {//枚举i
		t = t * mi % p;
		if (dict.count(t) != 0) return i * m - dict[t];
	}
	return -1;
}
int main() {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	ll b, n, p;
	cin >> p >> b >> n;
	ll ans = bsgs(b, n, p);
	if (ans == -1)cout << "no solution\n";
	else cout << ans << "\n";

	return 0;
}

进阶篇

求解

x a ≡ b ( m o d p ) x^a \equiv b \pmod p xab(modp)

其中 p p p 是个质数。

该模型可以通过一系列的转化为成 基础篇 中的模型,你可能需要了解关于 阶与原根 的知识。

由于式子中的模数 p p p 是一个质数,那么 p p p 一定存在一个原根 g g g。因此对于模 p p p 意义下的任意的数 x   ( 0 ≤ x < p ) x\ (0\le x<p) x (0x<p) 有且仅有一个数 i   ( 0 ≤ i < p − 1 ) i\ (0\le i<p-1) i (0i<p1) 满足 x = g i x = g^i x=gi

方法一

我们令 x = g c x=g^c x=gc g g g p p p 的原根(我们一定可以找到这个 g g g c c c),问题转化为求解 ( g c ) a ≡ b ( m o d p ) (g^c)^a \equiv b \pmod p (gc)ab(modp)。稍加变换,得到

( g a ) c ≡ b ( m o d p ) (g^a)^c \equiv b \pmod p (ga)cb(modp)

于是就转换成了我们熟知的 BSGS 的基本模型了,可以在 O ( p ) O(\sqrt p) O(p ) 解出 c c c,这样可以得到原方程的一个特解 x 0 ≡ g c ( m o d p ) x_0\equiv g^c\pmod p x0gc(modp)

方法二

我们仍令 x = g c x=g^c x=gc,并且设 b = g t b=g^t b=gt,于是我们得到

g a c ≡ g t ( m o d p ) g^{ac}\equiv g^t\pmod p gacgt(modp)

方程两边同时取离散对数得到

a c ≡ t ( m o d φ ( p ) ) ac\equiv t\pmod{\varphi(p)} act(modφ(p))

我们可以通过 BSGS 求解 g t ≡ b ( m o d p ) g^t\equiv b\pmod p gtb(modp) 得到 t t t,于是这就转化成了一个线性同余方程的问题。这样也可以解出 c c c,求出 x x x 的一个特解 x 0 ≡ g c ( m o d p ) x_0\equiv g^c\pmod p x0gc(modp)

找到所有解

在知道 x 0 ≡ g c ( m o d p ) x_0\equiv g^{c}\pmod p x0gc(modp) 的情况下,我们想得到原问题的所有解。首先我们知道 g φ ( p ) ≡ 1 ( m o d p ) g^{\varphi(p)}\equiv 1\pmod p gφ(p)1(modp),于是可以得到

∀   t ∈ Z ,   x a ≡ g c ⋅ a + t ⋅ φ ( p ) ≡ b ( m o d p ) \forall\ t \in \mathbb{Z},\ x^a \equiv g^{ c \cdot a + t\cdot\varphi(p)}\equiv b \pmod p  tZ, xagca+tφ(p)b(modp)

于是得到所有解为

∀   t ∈ Z , a ∣ t ⋅ φ ( p ) ,   x ≡ g c + t ⋅ φ ( p ) a ( m o d p ) \forall\ t\in \mathbb{Z},a\mid t\cdot\varphi(p),\ x\equiv g^{c+\frac{t\cdot\varphi(p)}{a}}\pmod p  tZ,atφ(p), xgc+atφ(p)(modp)

对于上面这个式子,显然有 a gcd ⁡ ( a , φ ( p ) ) ∣ t \frac{a}{\gcd(a,\varphi(p))} \mid t gcd(a,φ(p))at。因此我们设 t = a gcd ⁡ ( a , φ ( p ) ) ⋅ i t=\frac{a}{\gcd(a,\varphi(p))}\cdot i t=gcd(a,φ(p))ai,得到

∀   i ∈ Z , x ≡ g c + φ ( p ) gcd ⁡ ( a , φ ( p ) ) ⋅ i ( m o d p ) \forall \ i\in \mathbb{Z},x\equiv g^{c+\frac{\varphi(p)}{\gcd(a,\varphi(p))}\cdot i}\pmod p  iZ,xgc+gcd(a,φ(p))φ(p)i(modp)

这就是原问题的所有解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值