zhongzihao/bigfact_pow

大阶乘模质数的幂学习笔记

以下参考了这篇博客

\(n!\mod{p^{e}}\)(包括 \(p\) 的幂次和互质部分的模),其中 \(p\) 为质数,可以在 \(\mathcal{O}(pe+e\log_{p}n)\) 下完成(不考虑大整数部分的复杂度)。

定义 \(f(m)=\prod_{i=1,\text{gcd}(i,m)=1}i\)。那么有 \(n!=f(n)\cdot p^{\lfloor\frac{n}{p}\rfloor}\cdot\lfloor\frac{n}{p}\rfloor!\),也就是说我们可以通过 \(\log_{p}n\)\(f\) 的计算来得到答案。

\(n=up+v(0\le v<p)\),下面来计算 \(f(n)\)\[ \begin{aligned} f(n)&=\left(\prod_{i=0}^{u-1}\prod_{j=1}^{p-1}(ip+j)\right)\cdot\prod_{j=1}^{v}(up+j)\\ \end{aligned} \] 其中 \[ \begin{aligned} \prod_{i=1}^{x}(t+i)&=\sum_{i=0}^{x+1}\frac{\begin{bmatrix}x+1\\i\end{bmatrix}t^{i}}{t}\\ &=\sum_{i=0}^{x}\begin{bmatrix}x+1\\i+1\end{bmatrix}t^{i} \end{aligned} \] 因此 \[ \begin{aligned} f(n)&=\left(\prod_{i=0}^{u-1}\sum_{j=0}^{p-1}\begin{bmatrix}p\\j+1\end{bmatrix}(ip)^{j}\right)\cdot\sum_{j=0}^{v}\begin{bmatrix}v+1\\j+1\end{bmatrix}(up)^{j}\\ &=\left(\prod_{i=0}^{u-1}\sum_{j=0}^{\min\{p-1,e-1\}}\begin{bmatrix}p\\j+1\end{bmatrix}(ip)^{j}\right)\cdot\sum_{j=0}^{\min\{v,e-1\}}\begin{bmatrix}v+1\\j+1\end{bmatrix}(up)^{j}\\ \end{aligned} \] 首先我们可以预处理 \(\mathcal{O}(pe)\) 项的第一类斯特林数,右边这一项即可以 \(\mathcal{O}(e\log_{p}n)\) 的复杂度计算。我们对左边继续化简: \[ \begin{aligned} &=\left(\begin{bmatrix}p\\1\end{bmatrix}\right)^{u}\cdot\prod_{i=0}^{u-1}\sum_{j=0}^{\min\{p-1,e-1\}}\frac{\begin{bmatrix}p\\j+1\end{bmatrix}}{\begin{bmatrix}p\\1\end{bmatrix}}(ip)^{j}\\ &=\left(\begin{bmatrix}p\\1\end{bmatrix}\right)^{u}\cdot\prod_{i=0}^{u-1}\left(1+\sum_{j=1}^{\min\{p-1,e-1\}}\frac{\begin{bmatrix}p\\j+1\end{bmatrix}}{\begin{bmatrix}p\\1\end{bmatrix}}(ip)^{j}\right) \end{aligned} \] 左边可以把 \(\log_{p}n\) 次计算的 \(u\) 加起来,通过快速幂计算一次即可。这部分的复杂度是 \(\mathcal{O}(\log_{2}n)\)

下面我们证明,右边是关于 \(u\) 的一个 \(2e-2\) 次多项式:

\(g(i,x)=1+\sum_{j=1}^{t}a_{j}(ix)^{j}\)\(g(i,x)\) 关于 \(x\)\(\log\)\(\sum_{j=1}^{+\infty}b_{j}(ix)^{j}\),那么有: \[ \begin{aligned} &\log\prod_{i=0}^{u-1}g(i,x)\\ =&\sum_{i=0}^{u-1}\log g(i,x)\\ =&\sum_{j=1}^{+\infty}b_{j}\left(\sum_{i=0}^{u-1}i^{j}\right)x^{j}\\ =&\sum_{j=1}^{+\infty}b_{j}s_{j}(u)x^{j} \end{aligned} \] 其中 \(s_{j}(u)\) 是一个关于 \(u\)\(j+1\) 次多项式。 \[ \begin{aligned}\\ &\prod_{i=0}^{u-1}g(i,x)\\ =&\exp\left(\sum_{j=1}^{+\infty}b_{j}s_{j}(u)x^{j}\right)\\ =&\prod_{j=1}^{+\infty}\exp\left(b_{j}s_{j}(u)x^{j}\right) \end{aligned} \] 观察容易发现,结果多项式的第 \(i\) 项的系数是 \(u\) 的一个 \(2i\) 次多项式 \(t_{i}(u)\)(最高次在 \(j=1\) 取到)。即: \[ \begin{aligned} &=\sum_{i=0}^{+\infty}t_{i}(u)x^{i} \end{aligned} \]\(x=p\) 代入,有: \[ \begin{aligned} &=\sum_{i=0}^{e-1}t_{i}(u)p^{i} \end{aligned} \] 因此上式是一个关于 \(u\)\(2e-2\) 次多项式。

考虑使用插值计算。首先可以用 \(\mathcal{O}(pe)\) 的时间预处理出 \(g(0,p)\sim g(2e-2,p)\) 的值, 然后使用拉格朗日插值来计算。设 \(h(u)=\prod_{i=0}^{u-1}g(i,p)\),那么 \(h(u)=\sum_{i=0}^{2e-2}h(i)\prod_{j=0,j\neq i}^{2e-2}\frac{u-j}{i-j}\)。其中分母部分的阶乘逆元可以预处理,而分子部分也可以用前缀后缀积的技巧 \(\mathcal{O}(1)\) 查询。这样的总复杂度为 \(\mathcal{O}(e\log_{p}n)\)。但是这里存在一个小问题,分母中可能有 \(p\),因此我们必须将和 \(p\) 互质的部分和 \(p\) 的幂次分开处理。分母部分可以预处理问题不大,但是如果我们暴力试除分子,最坏可以达到 \(\mathcal{O}(\log_{p}^{2}n)\) 的复杂度,在 \(n\) 恰为 \(p\) 的幂次时取到。

首先我们证明,分母部分含 \(p\) 的个数至多为 \((2e-2)!\)\(p\) 的个数。注意到分母部分的绝对值等于 \(\displaystyle{\frac{(2e-2)!}{{2e-2\choose i}}}\),因此上面的结论是显然的。因此,分母部分 \(p\) 的个数为 \(\mathcal{O}(\frac{e}{p})\)

容易发现,\(h(u)\)\(p\) 互质,因此至少存在一个 \(i\),使得 \(\prod_{j=0,j\neq i}^{2e-2}\frac{u-j}{i-j}\)\(p\) 互质。也就是说,除了这个 \(u-i\) 以外,剩下的所有 \(u-j\)\(p\) 的个数的和为 \(\mathcal{O}(\frac{e}{p})\)。而对于这个 \(u-i\) 来说,显然我们只要分解出 \(e+\mathcal{O}(\frac{e}{p})\)\(p\),就没有再分解下去的必要了。这样这部分的复杂度就降为了 \(\mathcal{O}(e\log_{p}n)\)

总复杂度 \(\mathcal{O}(pe+e\log_{p}n)\)