离散对数

zzafanti orz

\(\log_a b\bmod N\)\(N\) 是素数。

首先不妨设底数为原根。

BSGS:设定阈值 \(B\),预处理 \(g^0,g^1,\dots,g^{B-1}\)\(g^0,g^B,g^{2B},\dots\) 扔到哈希表里,这样对于 \(Q\) 组询问就做到了 \(O\left(B+\dfrac{NQ}{B}\right)\),平衡一下得到 \(O(\sqrt{NQ})\)


首先预处理出来 \(1\sim\sqrt N\) 的离散对数。假设要求 \(\log x\),设 \(N=px+q\)(带余除法),那么:

\[\begin{align} N-q&=px\\ \log(N-q)&=\log p+\log x\\ \log x &= \log(N-q) - \log p\\ \log x &= (\log (-1)+\log q)-\log p \end{align} \]

\(p\le \sqrt N\),于是 \(\log p\) 是已知的,所以只需要求出来 \(\log q\),这个直接递归下去求解。和 \(O(1)\) 逆元的处理方式很像,效率也很高。

对于预处理的部分,相当于要做 \(O(\sqrt N)\) 次查询,于是复杂度为 \(O(N^{0.75})\)。但是根据 \(\log(xy) = \log x + \log y\),用类似线性筛的方法,求出来素数处的点值就够了,于是可以优化到 \(O\left(\dfrac{N^{0.75}}{\sqrt{\log N}}\right)\)

应用:给定 \(a_1,a_2,\dots,a_n\) 和素数 \(P\),求 \(\prod_{i=1}^n i^{a_i}\bmod P\)

用上面的离散对数可以直接线性筛出来 \(1\sim n\) 的离散对数,预处理离散对数后复杂度线性。

不过还有另一个更巧妙的做法:把每个数 \(i\) 的贡献拆到素数幂上,然后从大到小枚举 \(i\),把 \(i\) 的贡献拆到 \(p_i^w_i\)\(i/p_i^w_i\) 上,最后在素数处计算一下答案就好了,复杂度同样是线性,并且和模数无关。

posted @ 2025-09-01 19:47  user_10086  阅读(5)  评论(0)    收藏  举报