Loading

「题解」[LG5221] Product

\[\begin{aligned} \text{ans} &=\prod_{i=1}^n\prod_{j=1}^n\dfrac{\text{lcm}(i,j)}{\gcd(i,j)} \\ &=\prod_{i=1}^n\prod_{j=1}^n\dfrac{ij}{\gcd^2(i,j)} \\ &=\left(\prod_{i=1}^n\prod_{j=1}^nij\right)\times\left(\prod_{i=1}^n\prod_{j=1}^n\gcd(i,j)\right)^{-2} \\ &=\left(n!\right)^{2n}\times\left(\prod_{i=1}^n\prod_{j=1}^n\gcd(i,j)\right)^{-2} \\ &=\left(n!\right)^{2n}\times\left(\prod_{d=1}^n\prod_{i=1}^n\prod_{j=1}^nd\left[\gcd(i,j)=d\right]\right)^{-2} \\ &=\left(n!\right)^{2n}\times\left(\prod_{d=1}^nd^{\displaystyle\sum_{i=1}^n\sum_{j=1}^n\left[\gcd(i,j)=d\right]}\right)^{-2} \\ \end{aligned} \]

化简指数:

\[\begin{aligned} k &=\sum_{i=1}^n\sum_{j=1}^n\left[\gcd(i,j)=d\right] \\ &=\sum_{i=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\sum_{j=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\left[\gcd(i,j)=1\right] \\ &=\sum_{i=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\sum_{j=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\sum_{t\mid\gcd(i,j)}\mu(t) \\ &=\sum_{t=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\mu(t)\sum_{i=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\left[t\mid i\right]\sum_{j=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\left[t\mid j\right] \\ &=\sum_{t=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\mu(t)\sum_{i=1}^{\small\left\lfloor\dfrac{n}{dt}\right\rfloor}\sum_{j=1}^{\small\left\lfloor\dfrac{n}{dt}\right\rfloor}1 \\ &=\sum_{t=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\mu(t)\left\lfloor\frac{n}{dt}\right\rfloor^2 \\ \end{aligned} \]

带回原式:

\[\begin{aligned} \text{ans} &= \left(n!\right)^{2n}\times\left(\prod_{d=1}^nd^k\right)^{-2} \\ &=\left(n!\right)^{2n}\times\left(\prod_{d=1}^nd^{\displaystyle\sum_{t=1}^{\small\left\lfloor\dfrac{n}{d}\right\rfloor}\mu(t)\left\lfloor\frac{n}{dt}\right\rfloor^2}\right)^{-2} \\ &=\left(n!\right)^{2n}\times\left[\prod_{T=1}^n\left(\prod_{d\mid T}d^{\mu\left(\frac{T}{d}\right)}\right)^{\displaystyle\left\lfloor\frac{n}{dt}\right\rfloor^2}\right]^{-2} \\ &=\left(n!\right)^{2n}\times\left(\prod_{T=1}^ng\left(T\right)^{^{\displaystyle\left\lfloor\frac{n}{dt}\right\rfloor^2}}\right)^{-2} \end{aligned} \]

这个式子显然可以整除分块求解,问题转换为求 \(g(n)=\displaystyle\prod_{d\mid n}d^{\mu\left(\frac{n}{d}\right)}\) 的前缀积。

如果空间允许的话,我们可以直接预处理出 \(\mu,d,d^{-1}\),然后暴力枚举倍数求 \(g\),时间复杂度 \(\Theta(n \ln n)\)。但是 7.81MB 的空间限制不允许我们这么做。

分析一下 \(g\) 是否有特殊性质。

考虑 \(n\) 的唯一分解形式 \(n=\displaystyle\prod_{i=1}^{m}p_i^{k_i}\),则:

  • \(m=1\) 时,有 \(\displaystyle g(n)=n\times\left(p_1^{k_1-1}\right)^{-1}=p_1\)

  • \(m\neq 1\) 时,有 \(g(n)=1\),证明如下:

    由于 \(\mu\) 的定义,我们只需要考虑 \(\dfrac{n}{d}\) 不包含平方因子的情况。也就是说,\(\dfrac{n}{d}\) 一定是 \(\{p_1,p_2,p_3,\dots,p_m\}\) 的一个子集(记为 \(S\))内所有数的乘积(记为 \(c\)),当这个 \(|S|\) 为奇数时,\(g(n)\) 乘上 \(\left(\dfrac{n}{c}\right)^{-1}\),反之 \(g(n)\) 乘上 \(\dfrac{n}{c}\)

    我们对每一个 \(p_i\) 计算其对 \(g(n)\) 的贡献,有四种情况:

    1. \(p_i \in S\) ,且 \(|S|\) 为奇数,此时 \(p_i\)\(g(n)\) 的贡献为 \(\displaystyle p_i^{ -\left(k_i-1\right)2^{m-2} }\)
      (在剩下的 \(m - 1\) 个数中选奇/偶数个数均有 \(2^{m-2}\) 种方案,因此指数乘上 \(2^{m-2}\),下同)

    2. \(p_i \in S\) ,且 \(|S|\) 为偶数,此时 \(p_i\)\(g(n)\) 的贡献为 \(\displaystyle p_i^{ \left(k_i-1\right)2^{m-2} }\)

    3. \(p_i \not\in S\) ,且 \(|S|\) 为奇数,此时 \(p_i\)\(g(n)\) 的贡献为 \(\displaystyle p_i^{ -k_i2^{m-2} }\)

    4. \(p_i \not\in S\) ,且 \(|S|\) 为偶数,此时 \(p_i\)\(g(n)\) 的贡献为 \(\displaystyle p_i^{ k_i2^{m-2} }\)

    这四种情况的贡献相乘 \(=1\),也就是说对于每一个 \(p_i\) 其对 \(g(n)\) 的贡献均为 \(1\)。因此 \(g(n)=1\)

即:

\[g(n)= \begin{cases} p &n=p^k,p\in\mathbb{PRIME}\\ 1 &\text{otherwise} \end{cases} \]

使用线性筛筛出所有的质数,然后对于每个质数 \(p\),暴力枚举 \(p^k\) 即可求出 \(g\)

综上,我们得到了一个时间复杂度 \(\Theta(n)\) 并且使用空间 < 7.81MiB 的做法。

由于实际运用中埃氏筛的运行效率高于线性筛,因此代码中使用的是埃氏筛筛质数。

代码
#include <bits/stdc++.h>

#define reg register

using namespace std;

const uint N = 1e6, P = 104857601;

uint n, fac = 1, ans = 1, ptot = 1, pnum[78450], g[N + 1];
bitset<N + 1> isnp;

inline uint qpow(reg uint a, reg uint b) {
	reg uint ret = 1;
	for (; b; b >>= 1, a = 1ull * a * a % P) b & 1 ? ret = 1ull * ret * a % P : 0;
	return ret;
}

signed main() {
	scanf("%u", &n), pnum[g[0] = g[1] = 1] = 2;
	for (reg uint i = 3; i * i <= n; i += 2) if (isnp[i] == 0) for (reg uint j = i * i; j <= n; j += 2 * i) isnp.set(j);
	for (reg uint i = 3; i <= n; i += 2) if (isnp[i] == 0) pnum[++ptot] = i;
	for (reg uint i = 1; i <= ptot; i++) {
		g[pnum[i]] = pnum[i];
		for (reg uint j = pnum[i], k; 1ull * j * pnum[i] <= n;) g[j *= pnum[i]] = pnum[i];
	}
	for (reg uint i = 2; i <= n; i++) fac = 1ull * fac * i % P, g[i] = 1ull * (g[i] ? g[i] : 1) * g[i - 1] % P;
	for (reg uint l = 1, r, k; l <= n; l = r + 1)
		k = n / l, r = n / k, ans = 1ull * ans * qpow(1ull * g[r] * qpow(g[l - 1], P - 2) % P, 1ull * k * k % (P - 1)) % P;
	return printf("%u\n", 1ull * qpow(fac, 2 * n) * qpow(1ull * ans * ans % P, P - 2) % P), 0;
}
posted @ 2022-04-26 18:36  Aestas16  阅读(65)  评论(0编辑  收藏  举报