baby step giant step algorithm

本文探讨了形如az≡b mod p的模指数方程的求解方法,重点介绍了当gcd(a,p)=1和gcd(a,p)≠1时的不同解法。通过扩展欧几里得算法和迭代处理,提出了高效的求解策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

形如 az≡b mod pa^z\equiv b \ mod \ pazb mod p  a,b,pa,b,pabp 已知求 zzz.

如果 gcd(a,p)=1​gcd(a,p)=1​gcd(a,p)=1

​ 我们令z=xp+y&ThickSpace;(x,y&lt;p)z=x \sqrt p +y\; (x,y&lt;\sqrt p)z=xp+y(x,y<p)

az≡b⇒axp+y≡b⇒axp≡b⋅(a−1)y​a^z\equiv b \quad \Rightarrow a^{x\sqrt p + y}\equiv b \quad \Rightarrow a^{x\sqrt p}\equiv b\cdot (a^{-1})^y​azbaxp+ybaxpb(a1)y

∵ gcd(a,p)=1\because \ gcd(a,p)=1 gcd(a,p)=1 我们可以使用扩展欧几里得得到 a−1​a^{-1}​a1 .

​ 对于右边 y&lt;py&lt;\sqrt py<p 我们预处理 (a−1)i (0≤i&lt;p)(a^{-1})^i\ (0\le i&lt; \sqrt p)(a1)i (0i<p) 将结果存放在一个表中.

​ 我们枚举左边的 x (0≤x&lt;p)x \ (0\leq x &lt; \sqrt p)x (0x<p) 在表中查找即可.

​ 处理 (b⋅a−1)i,axp​(b\cdot a^{-1})^i,a^{x\sqrt p}​(ba1)i,axp 我们可以递推得到,复杂度O(p)​O(\sqrt p)​O(p) . 注意 q​\sqrt q​q 向上取整

​ 关键在于存储的方式以及查找的复杂度.bitset ?? .unoder_map??. hash?? .

如果 gcd(a,p)≠1​gcd(a,p)\neq 1 ​gcd(a,p)̸=1

az=a⋅az−1≡b⇒a⋅az−1+p⋅y=b​a^z=a\cdot a^{z-1}\equiv b\Rightarrow a\cdot a^{z-1} + p\cdot y=b​az=aaz1baaz1+py=b

​ 令 X=az−1​X = a^{z-1}​X=az1

⇒a⋅X+p⋅y=b\Rightarrow a\cdot X+p\cdot y=baX+py=b 等式两边同时除以 gcd(a,p)gcd(a,p)gcd(a,p) 如果 b%gcd(a,p)≠1​b\%gcd(a,p)\neq 1​b%gcd(a,p)̸=1无解.

​ (这里我们假定 XXX 可以取遍 [0,p−1][0,p-1][0,p1] ).

​ 那么我们得到了一个新式子 a′⋅X+p′⋅y=b′ (a′=a/gcd(a,p),p′=p/gcd(a,p),b′=b/gcd(a,p)​a&#x27;\cdot X+p&#x27;\cdot y=b&#x27; \ ( a&#x27;=a/gcd(a,p),p&#x27;=p/gcd(a,p),b&#x27;=b/gcd(a,p)​aX+py=b (a=a/gcd(a,p),p=p/gcd(a,p),b=b/gcd(a,p)

​ 我们 a′⋅X+p′⋅y=b′⇒a′⋅a⋅az−2≡b′ mod p′a&#x27;\cdot X+p&#x27;\cdot y=b&#x27; \Rightarrow a&#x27;\cdot a \cdot a^{z-2} \equiv b&#x27; \ mod \ p&#x27;aX+py=baaaz2b mod pX=a′⋅az−2​X = a&#x27;\cdot a^{z-2}​X=aaz2

⇒a⋅X+p′⋅y=b′\Rightarrow a\cdot X+p&#x27;\cdot y=b&#x27;aX+py=b 继续迭代到无解或 gcd(a,p′)=1​gcd(a,p&#x27;)=1​gcd(a,p)=1

​ 所以最后的式子可以写成 A⋅az−x=B mod P​A \cdot a^{z-x} = B \ mod \ P ​Aazx=B mod P , gcd(A,P)=1​gcd(A,P)=1​gcd(A,P)=1

az−x=B⋅A−1 mod Pa^{z-x} = B\cdot A^{-1} \ mod \ Pazx=BA1 mod P 利用 gcd(a,P)=1gcd(a,P)=1gcd(a,P)=1 时的情况可以解得 z−xz-xzx 答案加上 xxx 即可.

​ 这里还存在一个问题,当答案 z&lt;xz&lt;xz<x 时需要特判,由于迭代次数只有几十次 也就是说 x​x​x 不会很大.暴力检查即可.

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 5;
using ll = long long;
ll powmod(ll x,ll n,ll mod) {
	ll ret = 1;
	for(;n>0;n>>=1,x=x*x%mod) if(n&1) ret = ret*x%mod;
	return ret;
}
ll modI(ll a, int m) {
	return a<=1?1:(1-modI(m%a, a)*m)/a+m;
}
int BSGS(ll a,ll b,ll p) // a^x=b % p;
{
	a %= p,b %= p;
	ll a1=1,cnt=0,g;
	for(int i=0,res=1;i<100;++i) {
		if(res==b) return i;
		res = res*a%p;
	}
	while((g = __gcd(a,p))!=1){
		if(b%g) return -1;
		b/=g,p/=g;
		a1 = a1*(a/g)%p;cnt++;
	}
	b = modI(a1,p)*b%p;
	unordered_map<int,int> mp;
	int block = sqrt(p);if(block*block!=p) block++;
	ll inv = modI(a,p),res = b;
	for(int i=0;i<block;++i) {
		if(mp.count(res)==0) mp[res]=i;
		res = res*inv%p;
	}
	res = 1,inv = powmod(a,block,p);
	for(int i=0;i<block;++i) {
		if(mp.count(res)) return i*block+mp[res]+cnt;
		res = res*inv%p;
	}
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值