BSGS exBSGS 详解(大步小步算法)

我放弃挣扎了

upd :

我挣扎成功了

BSGS : Big Step Giant Step

额其实我也不懂这个算法和名字有什么关系,倒是有点根号分治的味道~

这个东西用来求解一个东西 \(x\) 使得:

\[a^x \equiv b \pmod p \]

其中 \(a,b,p\) 给定且 \(p\) 为质数

接下来直接上操作:

令 $$t = \left \lceil \sqrt{p}\right \rceil $$

令 $$x = i \times t - B$$ 那么由于 \(p\) 是质数所以我们可以进行一番操作将原式变形为 $$a^{i\times t - B} \equiv b \pmod p$$

进一步得到

\[a^{i\times t} \equiv b^B \pmod p \]

注意!!!

这一步是进行了除法,必须保证逆元存在,而这等价于 \(a^B,p\) 互质,进而等价于 \(a,p\) 互质,所以其实只要求 \(a,p\) 互质即可!!

然后发现这里的 \(i \in [0,t] , B \in [0,t-1]\) 这样可以凑出来所有的 \(x\) 所以这两个东东都是 \(\sqrt{p}\) 级别的。那么考虑将右边的 \(b^B\) 插入哈希表记录对应的 \(B\) ,然后 \(O(\sqrt{p})\) 枚举左边的 \(a^{i\times t}\) 查询对应的哈希表即可。然后注意特判 \(i \times t - B \ge 0\) 即可

map<int,int>mp;
inline int BSGS(int a,int b,int p,int mul){
    b %= p;
	int t = ceil(sqrt(p));
	mp.clear();
    if(a % p == 0 && b)return -1;//如果b mod p > 0 && a mod p == 0 无解
    int res = 1;
    for(int i=0;i<t;++i,res=1ll*a*res%p)mp[1ll*res*b%p] = i;
    int base = res;res = mul;
    if(base == 0)return b == 0 ? 1 : -1;//a^t mod p == 0
    for(int i=0;i<=t;res=1ll*res*base%p,++i)
    if(mp.count(res))
        if(i*t-mp[res]>=0)return i*t-mp[res];
	return -1;
}

exBSGS

这里其实就是把 \(p\) 扩展到任意数了。

那么这里的 \(a,p\) 不互质了,我们考虑把他变成互质的不就好了!

重新观察式子

\[a^{x} \equiv b \pmod p \]

首先令 \(g = \gcd (a,p)\)

方程可以变为

\[\frac{a}{g} \times a^{x-1} \equiv \frac{b}{g} \pmod {\frac{p}{g}} \]

无解情况的话就是 \(g \nmid b\)\(b \ne 1\) 因为 \(b = 1\) 直接 \(x = 0\) 就好了,别的手推下不定方程很好证明。

于是我们可以重复这个过程,直至 \(\gcd (a,p) = 1\) 并且得到了 \(k\)\(g\)

令 $u = {\textstyle \prod_{i=1}^{k}} \frac{a}{g_{i}} ,v = \textstyle \prod_{i=1}^{k}g_{i} $你会发现每个 \(\frac {a}{g_{i}}\) 都与现在的 \(\frac{p}{v}\) 互质,因为 \(\frac{p}{v}\) 现在与 \(a\) 互质,自然与 \(\frac{a}{g_{i}}\) 互质,所以 \(u\)\(p\) 互质,所以存在逆元。

\[a^{x-k} \times u \equiv \frac{b}{v } \pmod {\frac{p}{v}} \]

这个就变成了普通的 BSGS 辣!

inline int exBSGS(int a,int b,int p){
    a %= p;b %= p;
	if(b == 1 || p == 1)return 0;
	int g = __gcd(a,p),k = 0,mul = 1;
	while(g > 1){
		if(b % g)return -1;
		++k;
		b /= g;
		p /= g;
		mul = 1ll * mul * (a / g) % p;
		if(mul == b)return k;
		g = __gcd(a,p);	
	}
	int ans = BSGS(a,b,p,mul);
	if(ans == -1)return ans;
	return ans + k;
}
posted @ 2022-09-03 10:37  Xu_brezza  阅读(156)  评论(1编辑  收藏  举报