一、开头
(浙江省神犇协会)
神犇1号:ZJOI 2018的题大家都AK了吗?
全体神犇:AK了!
神犇1号:7号神犇,你认识那个弱弱的xyz32768吗?
神犇7号:是的,我认识!我现在就去D他!
(X省Y市)
神犇7号:告诉你,ZJ的神犇协会从此有一个规矩:第1天,协会派我,也就是7号神犇来D人,第2天,协会就派49号神犇来D人,第3天,就派343号神犇来D人,以此类推。我们这里的神犇人数为
109+6
10
9
+
6
,所以,如果是第
n
n
天,
就派号神犇来D人。
我们这里最巨的神犇是
168812736
168812736
号,就考考你:最少在第几天,这号神犇会来D你?
xyz32768:难道,一个一个枚举
n
n
?
神犇7号:如果想不出来的话,我马上去叫168812736号神犇出来!
xyz32768:我还真的不会什么高端的数论算法。
神犇7号:168812736号神犇,在浙江吗?我又D了一个弱鸡!
神犇168812736号:切,BSGS这么水的算法,我们协会里每一个人都会,就你不会,辣鸡!
xyz32768:BSGS?北上广深?拔山盖世?
神犇7号&神犇168812736号:哈,菜!
二、引入
开头中ZJ神犇7号提出的问题就是一个经典模型:
给定(
C
C
是质数),求满足
的最小正整数 x x 。
如果暴力求解的话,复杂度是的,不足以通过神犇7号给出的 109+7 10 9 + 7 的模数。而BSGS算法可以实现 O(C−−√) O ( C ) 的复杂度。
BSGS(Baby Step Giant Step),即先小步后大步。
根据费马小定理,有 AC−1≡1(modC) A C − 1 ≡ 1 ( mod C ) 。所以, Ax A x 的值满足周期性变化,且存在一个周期为 x∈[1,C) x ∈ [ 1 , C ) 。
三、预备知识
- 哈希表
- 逆元
四、算法流程
(1)先取
S=⌈C−−√⌉
S
=
⌈
C
⌉
。
(2)把
A
A
,,
A3
A
3
,
A4
A
4
,…,
AS
A
S
模
C
C
的值存入哈希表。
(3)按顺序从
0
0
到,考虑是否存在
j
j
使得。
上式中
1≤j≤S
1
≤
j
≤
S
。把
Ai×S+j
A
i
×
S
+
j
拆解成
Ai×S×Aj
A
i
×
S
×
A
j
。
将式子移项:
其中 −1 − 1 是乘法逆元。
这时候可以先算出 B×(Ai×S)−1modC B × ( A i × S ) − 1 mod C 的值,
然后在哈希表中查询是否有这个值,如果存在合法的,最小的 j j ,
则答案。
五、扩展BSGS算法
如果
C
C
不是质数,那么可能不存在逆元。
这时候就需要转化,使得逆元存在。
蒟蒻xyz32768不会,只好放网址了:
http://blog.youkuaiyun.com/zzkksunboy/article/details/73162229
六、模板
int BSGS() {
int i, x = 1; for (i = 1; i <= S; ++i) {
x = 1ll * x * A % C; if (!ha[x]) ha[x] = i;
}
int dalao = qpow(x, C - 2, C), tmp = B;
for (i = 0; i < S; ++i) {
if (ha[tmp]) {
int res = i * S + ha[tmp]; ha.clear(); return res;
}
tmp = 1ll * tmp * dalao % C;
}
ha.clear(); return -1;
}