BSGS exBSGS 详解(大步小步算法)
我放弃挣扎了
upd :
我挣扎成功了
BSGS : Big Step Giant Step
额其实我也不懂这个算法和名字有什么关系,倒是有点根号分治的味道~
这个东西用来求解一个东西 \(x\) 使得:
其中 \(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^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\) 不互质了,我们考虑把他变成互质的不就好了!
重新观察式子
首先令 \(g = \gcd (a,p)\)
方程可以变为
无解情况的话就是 \(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\) 互质,所以存在逆元。
这个就变成了普通的 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;
}