【题解】Luogu-P7486 「Stoi2031」彩虹

P7486 「Stoi2031」彩虹

请确保宁已经熟练掌握:

  • 莫比乌斯反演
  • 形如 \(\sum_{d\mid n} f(d)\),其中 \(f\) 为积性函数的 \(\Theta(n\ln n)\) 的筛法。

Description

  • 多测,数据组数为 \(t\)

  • 给定一个正整数 \(n\),然后 \(t\) 组询问,每组给出两个满足 \(1\le l\le r\le n\) 的正整数 \(l, r\),请求出

    \[\left[\prod_{i = l}^r \prod_{j = l}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)} \right] \bmod 32465177 \]

  • 对于 \(100\%\) 的数据,\(1 \le n \le 10^6, 1 \le t \le 10, 1 \le l_i \le r_i \le n\)

Solution

考虑用前缀积 + 容斥。

为方便表示,设 \(f(n, m) = \prod_{i = 1}^n \prod_{i = 1}^m \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}\)

\[\begin{aligned} \prod_{i = l}^r \prod_{j = l}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)} & = \prod_{i = l}^r \dfrac{\prod\limits_{j = 1}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}{\prod\limits_{j = 1}^{l - 1} \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}} \\ & = \dfrac{\prod\limits_{i = 1}^r \dfrac{\prod\limits_{j = 1}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}{\prod\limits_{j = 1}^{l - 1} \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}}{\prod\limits_{i = 1}^{l - 1} \dfrac{\prod\limits_{j = 1}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}{\prod\limits_{j = 1}^{l - 1} \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}} \\ & = \dfrac{\dfrac{\prod\limits_{i = 1}^r \prod\limits_{j = 1}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}{\prod\limits_{i = 1}^r \prod\limits_{j = 1}^{l - 1} \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}}{\dfrac{\prod\limits_{i = 1}^{l - 1} \prod\limits_{j = 1}^r \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}{\prod\limits_{i = 1}^{l - 1} \prod\limits_{j = 1}^{l - 1} \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}}} \\ & = \dfrac{f(r, r) f(l - 1, l - 1)}{f(r, l - 1) f(l - 1, r)} \end{aligned} \]

观察到 \(f(n, m) = f(m, n)\),不妨设 \(n\le m\)

\[\begin{aligned} f(n, m) & = \prod_{i = 1}^n \prod_{j = 1}^m \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)} \\ & = \prod_{i = 1}^n \prod_{j = 1}^m \left[\dfrac{ij}{\gcd(i, j)} \right]^{\frac{ij}{\gcd(i, j)}} \\ \end{aligned} \]

发现若 \(\gcd(i, j)\ne d\),则 \(\dfrac{ij}{\gcd(i, j)} [\gcd(i, j) = d] = 0\),那么如果它作为指数,有 \(\left[\dfrac{ij}{\gcd(i, j)} \right]^{\frac{ij}{\gcd(i, j)} [\gcd(i, j) = d]} = 1\),刚好满足这一项不符合要求。

所以变成

\[\begin{aligned} & = \prod_{d = 1}^n \prod_{i = 1}^n \prod_{j = 1}^m \left(\dfrac{ij}{d}\right)^{\frac{ij}{d} [\gcd(i, j) = d]} \\ & = \prod_{d = 1}^n \prod_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} (ijd)^{ijd [\gcd(i, j) = 1]} \\ & = \prod_{d = 1}^n \prod_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} (ijd)^{ijd \sum_{k\mid \gcd(i, j)} \mu(k)} \end{aligned} \]

将指数的加改为底数的乘

\[\begin{aligned} & = \prod_{d = 1}^n \prod_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} \prod_{k\mid \gcd(i, j)} (ijd)^{ijd\, \mu(k)} \\ & = \prod_{d = 1}^n \prod_{k = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} [k\mid i] \prod_{j = 1}^{\left\lfloor\frac{m}{d}\right\rfloor} [k\mid j] (ijd)^{ijd\, \mu(k)} \\ & = \prod_{d = 1}^n \prod_{k = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{i = 1}^{\left\lfloor\frac{n}{dk}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{dk}\right\rfloor} (ijdk^2)^{ijdk^2\mu(k)} \\ & = \prod_{d = 1}^n \prod_{k = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \prod_{i = 1}^{\left\lfloor\frac{n}{T}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} (ijkT)^{ijkT\, \mu(k)} \\ & = \prod_{T = 1}^n \prod_{k\mid T} \prod_{i = 1}^{\left\lfloor\frac{n}{T}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} (ijkT)^{ijkT\, \mu(k)} \\ & = \prod_{T = 1}^n \prod_{k\mid T} \left[\prod_{i = 1}^{\left\lfloor\frac{n}{T}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} (ijkT)^{ij} \right]^{kT\, \mu(k)} \\ & = \prod_{T = 1}^n \prod_{k\mid T} \left\{ \left[\prod_{i = 1}^{\left\lfloor\frac{n}{T}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} (ij)^{ij} \cdot \prod_{i = 1}^{\left\lfloor\frac{n}{T}\right\rfloor} \prod_{j = 1}^{\left\lfloor\frac{m}{T}\right\rfloor} (kT)^{ij} \right]^{k\, \mu(k)} \right\}^T \end{aligned} \]

化简后面两项。设一个函数 \(S(n) = \sum_{i = 1}^n i\),再设 \(g(n) = \prod_{i = 1}^n i^i\)

\[\begin{aligned} \prod_{i = 1}^n \prod_{j = 1}^m (ij)^{ij} & = \prod_{i = 1}^n \prod_{j = 1}^m i^{ij} \cdot j^{ij} \\ & = \prod_{i = 1}^n \prod_{j = 1}^m i^{ij} \cdot \prod_{j = 1}^m \prod_{i = 1}^n j^{ji} \\ & = \prod_{i = 1}^n i^{i\sum_{x = 1}^m x} \cdot \prod_{j = 1}^m j^{j\sum_{y = 1}^n y} \\ & = \left(\prod_{i = 1}^n i^i\right)^{\sum_{x = 1}^m x} \cdot \left(\prod_{j = 1}^m j^j\right)^{\sum_{y = 1}^n y} \\ & = g(n)^{S(m)} \cdot g(m)^{S(n)} \end{aligned} \]

设它为 \(h(n, m)\) 吧。

然后

\[\begin{aligned} \prod_{i = 1}^n \prod_{j = 1}^m (kT)^{ij} & = (kT)^{\sum_{i = 1}^n \sum_{j = 1}^m ij} \\ & = (kT)^{\sum_{i = 1}^n i \sum_{j = 1}^m j} \\ & = (kT)^{S(n) S(m)} \end{aligned} \]

回代

\[\begin{aligned} & = \prod_{T = 1}^n \prod_{k\mid T} \left\{ \left[h\left(\left\lfloor\dfrac{n}{T}\right\rfloor, \left\lfloor\dfrac{m}{T}\right\rfloor \right) (kT)^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right)} \right]^{k\, \mu(k)} \right\}^T \\ & = \prod_{T = 1}^n \prod_{k\mid T} \left[h\left(\left\lfloor\dfrac{n}{T}\right\rfloor, \left\lfloor\dfrac{m}{T}\right\rfloor \right)^{k\, \mu(k)}\cdot k^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right) k\, \mu(k)} \cdot T^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right) k\, \mu(k)} \right]^T \end{aligned} \]

\(\alpha(n) = \sum_{d\mid n} d\, \mu(d)\),另设 \(\beta(n) = \prod_{d\mid n} d^{d\, \mu(d)}\)

\[= \prod_{T = 1}^n \left[h\left(\left\lfloor\dfrac{n}{T}\right\rfloor, \left\lfloor\dfrac{m}{T}\right\rfloor \right)^{\alpha(T)} \cdot \beta(T)^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right)} \cdot T^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right) \alpha(T)} \right]^T \]

为简洁表示,再设 \(\delta(n) = \left[\beta(n) \cdot n^{\alpha(n)} \right]^n\)

\[= \prod_{T = 1}^n h\left(\left\lfloor\dfrac{n}{T}\right\rfloor, \left\lfloor\dfrac{m}{T}\right\rfloor \right)^{\alpha(T) T} \cdot \delta(T)^{S\left(\left\lfloor\frac{n}{T}\right\rfloor \right) S\left(\left\lfloor\frac{m}{T}\right\rfloor \right)} \]

数论分块:

  • 第一项底数相同,预处理指数的前缀和即可;
  • 第二项指数相同,预处理底数的前缀积即可。

模数 \(p = 32465177\) 是质数,根据欧拉定理可以将指数 \(\bmod (p - 1)\) 降到 \(\Omicron(p)\) 级别。

以上所有需要用到的东西:

  • \(S(n) = \sum_{i = 1}^n i\)\(\Theta(1)\) 计算,\(S(n)\) 都作为指数出现,所以 \(\bmod (p - 1)\)
  • \(g(n) = \prod_{i = 1}^n i^i\):预处理 \(\Omicron(n\log n)\),查询 \(\Theta(1)\)
  • \(h(n, m) = g(n)^{S(m)} \cdot g(m)^{S(n)}\):在可以 \(\Theta(1)\) 得到 \(S,g\) 的值的情况下是 \(\Omicron(\log p)\) 计算的。
  • \(d\, \mu(d)\):令其为 \(\gamma(d)\)。把这个在线性筛时顺便算出来,\(\Theta(n)\)。观察到 \(\gamma(d)\) 都作为指数出现,所以可以将其 \(\bmod (p - 1)\) 并转成正数。
  • \(\alpha(n) = \sum_{d\mid n} \gamma(d)\):预处理 \(\Theta(n\ln n)\),查询 \(\Theta(1)\)。作为指数出现,\(\bmod (p - 1)\)
  • \(\alpha(n) n\):令其为 \(\zeta(n)\)。预处理 \(\Theta(n)\),查询 \(\Theta(1)\)。作为指数出现,\(\bmod (p - 1)\)
  • \(d^{d\, \mu(d)}\):令其为 \(\lambda(d)\)。也是在线性筛中做,但它使线性筛多了个 \(\log p\)
  • \(\beta(n) = \prod_{d\mid n} \lambda(d)\):预处理 \(\Theta(n\ln n)\),查询 \(\Theta(1)\)
  • \(\delta(n) = \left[\beta(n) \cdot n^{\alpha(n)} \right]^n\):预处理 \(\Omicron(n\log p)\),查询 \(\Theta(1)\)

数论分块是 \(\Omicron\left(\sqrt{n}\log p\right)\) 的,即计算 \(f(n, m) = \prod_{i = 1}^n \prod_{i = 1}^m \operatorname{lcm}(i, j)^{\operatorname{lcm}(i, j)}\)\(\Omicron\left(\sqrt{n}\log p\right)\) 的。

\(t\) 次询问,时间是 \(\Omicron(t\sqrt{n}\log p)\) 的。

加上预处理,总时间复杂度为 \(\Omicron(n\log p + n\ln n + t\sqrt{n}\log p)\) 的,由于 \(t\le 10\) 过小,所以真正在 \(\Omicron(n\log p)\) 级别内。

Code

// 18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#define Debug(x) cout << #x << "=" << x << endl
typedef long long ll;
using namespace std;

const int MAXN = 1e6 + 5;
const int MOD = 32465177;

int qpow(int a, int b)
{
	int base = a, ans = 1;
	while (b)
	{
		if (b & 1)
		{
			ans = (ll)ans * base % MOD;
		}
		base = (ll)base * base % MOD;
		b >>= 1;
	}
	return ans;
}

int inv(int a)
{
	return qpow(a, MOD - 2);
}

int p[MAXN], g[MAXN], mu[MAXN], gamma[MAXN], alpha[MAXN], zeta[MAXN], zeta_sum[MAXN], lambda[MAXN], beta[MAXN], delta[MAXN], delta_pro[MAXN], delta_pro_inv[MAXN], delta_pro_pro[MAXN], delta_pro_pro_inv[MAXN];
bool vis[MAXN];

void pre(int n)
{
	g[1] = mu[1] = gamma[1] = lambda[1] = beta[1] = delta[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		beta[i] = 1;
		g[i] = (ll)g[i - 1] * qpow(i, i % (MOD - 1)) % MOD;
		if (!vis[i])
		{
			p[++p[0]] = i;
			mu[i] = -1;
		}
		gamma[i] = (i * mu[i] % (MOD - 1) + MOD - 1) % (MOD - 1);
		lambda[i] = qpow(i, gamma[i]);
		for (int j = 1; j <= p[0] && i * p[j] <= n; j++)
		{
			vis[i * p[j]] = true;
			if (i % p[j] == 0)
			{
				mu[i * p[j]] = 0;
				break;
			}
			mu[i * p[j]] = mu[i] * mu[p[j]];
		}
	}
	
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; i * j <= n; j++)
		{
			alpha[i * j] = (alpha[i * j] + gamma[i]) % (MOD - 1);
			beta[i * j] = (ll)beta[i * j] * lambda[i] % MOD;
		}
	}
	
	delta_pro[0] = delta_pro_pro[0] = delta_pro_inv[0] = delta_pro_inv[1] = 1;
	for (int i = 1; i <= n; i++)
	{
		zeta[i] = (ll)alpha[i] * i % (MOD - 1);
		zeta_sum[i] = (zeta_sum[i - 1] + zeta[i]) % (MOD - 1);
		delta[i] = qpow((ll)beta[i] * qpow(i, alpha[i]) % MOD, i % (MOD - 1));
		delta_pro[i] = (ll)delta_pro[i - 1] * delta[i] % MOD;
		delta_pro_pro[i] = (ll)delta_pro_pro[i - 1] * delta_pro[i] % MOD;
	}
	
	delta_pro_pro_inv[n] = inv(delta_pro_pro[n]);
	for (int i = n - 1; i >= 1; i--)
	{
		delta_pro_pro_inv[i] = (ll)delta_pro_pro_inv[i + 1] * delta_pro[i + 1] % MOD;
		delta_pro_inv[i + 1] = (ll)delta_pro_pro_inv[i + 1] * delta_pro_pro[i] % MOD;
	}
}

int S(int n)
{
	return (ll)n * (n + 1) / 2 % (MOD - 1);
}

int h(int n, int m)
{
	return (ll)qpow(g[n], S(m)) * qpow(g[m], S(n)) % MOD;
}

int GetZetaSum(int l, int r)
{
	return (zeta_sum[r] - zeta_sum[l - 1] + MOD - 1) % (MOD - 1);
}

int GetDeltaPro(int l, int r)
{
	return (ll)delta_pro[r] * delta_pro_inv[l - 1] % MOD;
}

int f(int n, int m)
{
	if (n > m)
	{
		swap(n, m);
	}
	int res = 1;
	for (int l = 1, r; l <= n; l = r + 1)
	{
		int k1 = n / l, k2 = m / l;
		r = min(n / k1, m / k2);
		res = (ll)res * qpow(h(k1, k2), GetZetaSum(l, r)) % MOD * qpow(GetDeltaPro(l, r), (ll)S(k1) * S(k2) % (MOD - 1)) % MOD;
	}
	return res;
}

int main()
{
	int t, n;
	scanf("%d%d", &t, &n);
	pre(n);
	while (t--)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		int a = (ll)f(r, r) * f(l - 1, l - 1) % MOD, b = (ll)f(r, l - 1) * f(l - 1, r) % MOD;
		printf("%d\n", (ll)a * inv(b) % MOD);
	}
	return 0;
}
posted @ 2022-01-20 11:35  mango09  阅读(38)  评论(0编辑  收藏  举报
-->