一些奇怪的数论预处理算法
注意:以下内容可能全都是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\) 时可以求出
即可得到 \(\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}\),分类讨论:
-
\(p\le x^{\frac 1 4}\),此时易推得 \(r_1p\le \sqrt x\)
-
\(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)\) 单组(而且常数应该还不错?)。

浙公网安备 33010602011771号