一些奇怪的数论预处理算法

注意:以下内容可能全都是useless algorithm。
以下默认 \(p\) 为模数。


在线 \(\mathcal O(1)\) 求逆元

参考这篇博客,可以在这里提交。

需要 \(\mathcal O(p^{\frac 2 3})\) 的预处理。


在线 \(\mathcal O(1)\) 求gcd

参考这里

需要 \(\mathcal O(\text{值域})\) 的预处理。

具体思路是用线性筛将一个数分解成至多3个数,使得这3个数要么是质数要么是不超过 \(\sqrt{\text{值域}}\) 的数。

同时我们再预处理一个 \(\sqrt{\text{值域}}\times \sqrt{\text{值域}}\) 的表,表示 \(\sqrt{\text{值域}}\) 内的数两两gcd,递推可以不带log。

于是求 \(\gcd(a,b),a=xyz\) 时可以求出

\[d_1=\gcd(x,b\bmod x),d_2=\gcd(y,b/d_1\bmod y),d_3=\gcd(z,b/d_1d_2\bmod z) \]

即可得到 \(\gcd(a,b)=d_1d_2d_3\)

\(x\) 分解的方法是,找到 \(x\) 的最小质因子 \(p\),根据 \(x/p\) 的分解 \(x/p=r_1r_2r_3(r_1\le r_2\le r_3)\) 得到 \(x\) 的分解 \(x=(r_1p)r_2r_3\)

显然只需证明 \(r_1p\) 为质数或不超过 \(\sqrt x\) 即可。显然有 \(r_1\le (x/p)^{\frac 1 3}\),分类讨论:

  1. \(p\le x^{\frac 1 4}\),此时易推得 \(r_1p\le \sqrt x\)

  2. \(p\gt x^{\frac 1 4}\),此时 \(x\) 易知只有至多三个质因子,于是必有 \(r_1=1\)\(\square\)

但由于最终求一次gcd很可能需要3次取模+除法+查表,常数非常大,据说有时跑不过辗转相除。


在线 \(\mathcal O(\log p)\) 求固定模数下离散对数

需要打表或者 \(\mathcal O\left(\dfrac{p^{3/4}}{\sqrt{\log p}}\right)\) 的预处理。这个预处理是自己yy的,很可能能进一步优化

我们只需能 \(\mathcal O(\log p)\) 求出某个原根 \(g\) 为底时任意数的离散对数。

则一般离散对数问题 \(A^x=B,A=g^a,B=g^b\) 只需再求解线性同余方程 \(ax\equiv b\pmod {p-1}\) 即可。

我们考虑预处理出 \(\sqrt p\) 内的数的离散对数,那么此时若要求解 \(x\gt \sqrt p\) 的离散对数,可以采用如下的方法:

做带余除法 \(p=ax+b(b\lt x)\),则有 \(x\equiv \dfrac{-b}{a}\pmod p\),且 \(a\le \sqrt p\),所以 \(\log a\) 是已知的。

\(\log(-1)=\dfrac{p-1}{2}\) 是显然的。于是若我们知道 \(\log b\) 即可求出 \(\log x=\log(-1)+\log b-\log a\)。递归求解 \(\log b\) 即可。

但是复杂度没有保证,因此我们稍作变形:若 \(b\le x/2\),直接向下递归;否则考虑 \(p=ax+b=(a+1)x+(b-x)\implies x\equiv\dfrac{x-b}{a+1}\pmod p\),递归求解 \(\log(x-b)\) 即可。

好的,所以现在我们仅需处理出 \(\sqrt p\) 内的数的离散对数了!我们考虑线性筛,则仅需处理出 \(\sqrt p\) 内的素数的离散对数。

于是可以打表,这个其实应该最实用。但是如果模数没有提前给定,我们可以直接BSGS求解这些数的离散对数。

注意BSGS是可以平衡预处理复杂度和查询复杂度的,根号平衡一下就得到了上面的 \(\mathcal O\left(\dfrac{p^{3/4}}{\sqrt{\log p}}\right)\)

这个算法的递归求解常数应该与辗转相除求gcd类似(实测挺快的),但是这个预处理由于BSGS需要开一个很大的哈希表应该是挺慢的……总之推荐打表。

模质数求逆元也可以用这个带余除法做到不预处理,\(\mathcal O(\log x)\) 单组(而且常数应该还不错?)。

posted @ 2022-04-05 10:36  秋叶冬雪  阅读(234)  评论(0)    收藏  举报