Description
-
给定整数 n n n,请求出
[ ∏ i = 1 n ∏ j = 1 n lcm ( i , j ) gcd ( i , j ) ] m o d 104857601 \left[\prod_{i = 1}^n \prod_{j = 1}^n \dfrac{\operatorname{lcm}(i, j)}{\gcd(i, j)} \right] \bmod 104857601 [i=1∏nj=1∏ngcd(i,j)lcm(i,j)]mod104857601 -
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 6 1\le n\le 10^6 1≤n≤106。
Solution
∏
i
=
1
n
∏
j
=
1
n
lcm
(
i
,
j
)
gcd
(
i
,
j
)
=
∏
i
=
1
n
∏
j
=
1
n
i
j
gcd
(
i
,
j
)
2
=
∏
i
=
1
n
∏
j
=
1
n
i
j
[
∏
i
=
1
n
∏
j
=
1
n
gcd
(
i
,
j
)
]
2
\begin{aligned} \prod_{i = 1}^n \prod_{j = 1}^n \dfrac{\operatorname{lcm}(i, j)}{\gcd(i, j)} & = \prod_{i = 1}^n \prod_{j = 1}^n \dfrac{ij}{\gcd(i, j)^2} \\ & = \dfrac{\prod\limits_{i = 1}^n \prod\limits_{j = 1}^n ij}{\left[\prod\limits_{i = 1}^n \prod\limits_{j = 1}^n \gcd(i, j) \right]^2} \end{aligned}
i=1∏nj=1∏ngcd(i,j)lcm(i,j)=i=1∏nj=1∏ngcd(i,j)2ij=[i=1∏nj=1∏ngcd(i,j)]2i=1∏nj=1∏nij
对于分子
∏
i
=
1
n
∏
j
=
1
n
i
j
=
∏
i
=
1
n
i
n
⋅
n
!
=
(
n
!
)
n
⋅
(
n
!
)
n
=
(
n
!
)
2
n
\begin{aligned} \prod_{i = 1}^n \prod_{j = 1}^n ij & = \prod_{i = 1}^n i^n\cdot n! \\ & = (n!)^n \cdot (n!)^n \\ & = (n!)^{2n} \end{aligned}
i=1∏nj=1∏nij=i=1∏nin⋅n!=(n!)n⋅(n!)n=(n!)2n
对于分母(忽略
2
2
2 次方)
∏
i
=
1
n
∏
j
=
1
n
gcd
(
i
,
j
)
=
∏
d
=
1
n
∏
i
=
1
n
∏
j
=
1
n
d
[
gcd
(
i
,
j
)
=
d
]
=
∏
d
=
1
n
∏
i
=
1
⌊
n
d
⌋
∏
j
=
1
⌊
n
d
⌋
d
[
gcd
(
i
,
j
)
=
1
]
=
∏
d
=
1
n
d
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
n
d
⌋
[
gcd
(
i
,
j
)
=
1
]
\begin{aligned} \prod_{i = 1}^n \prod_{j = 1}^n \gcd(i, j) & = \prod_{d = 1}^n \prod_{i = 1}^n \prod_{j = 1}^n 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{n}{d}\right\rfloor} d[\gcd(i, j) = 1] \\ & = \prod_{d = 1}^n d^{\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} [\gcd(i, j) = 1]} \end{aligned}
i=1∏nj=1∏ngcd(i,j)=d=1∏ni=1∏nj=1∏nd[gcd(i,j)=d]=d=1∏ni=1∏⌊dn⌋j=1∏⌊dn⌋d[gcd(i,j)=1]=d=1∏nd∑i=1⌊dn⌋∑j=1⌊dn⌋[gcd(i,j)=1]
拆指数
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
n
d
⌋
[
gcd
(
i
,
j
)
=
1
]
=
∑
k
=
1
⌊
n
d
⌋
μ
(
k
)
⌊
n
d
k
⌋
2
\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} [\gcd(i, j) = 1] = \sum_{k = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \mu(k) \left\lfloor\dfrac{n}{dk}\right\rfloor^2
i=1∑⌊dn⌋j=1∑⌊dn⌋[gcd(i,j)=1]=k=1∑⌊dn⌋μ(k)⌊dkn⌋2
代回去
∏
d
=
1
n
d
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
n
d
⌋
[
gcd
(
i
,
j
)
=
1
]
=
∏
d
=
1
n
d
∑
k
=
1
⌊
n
d
⌋
μ
(
k
)
⌊
n
d
k
⌋
2
\prod_{d = 1}^n d^{\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum_{j = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} [\gcd(i, j) = 1]} = \prod_{d = 1}^n d^{\sum_{k = 1}^{\left\lfloor\frac{n}{d}\right\rfloor} \mu(k) \left\lfloor\frac{n}{dk}\right\rfloor^2}
d=1∏nd∑i=1⌊dn⌋∑j=1⌊dn⌋[gcd(i,j)=1]=d=1∏nd∑k=1⌊dn⌋μ(k)⌊dkn⌋2
指数用欧拉定理
m
o
d
(
p
−
1
)
\bmod (p - 1)
mod(p−1) 转成正数并降至
O
(
p
)
\Omicron(p)
O(p) 级别。
暴力枚举 + 整除分块。
时间复杂度为 O ( ∑ i = 1 n n i ⋅ log p ) = O ( log p ∑ i = 1 n n i ) \Omicron\left(\sum_{i = 1}^n \sqrt{\dfrac{n}{i}} \cdot \log p \right) = \Omicron(\log p \sum_{i = 1}^n \sqrt{\dfrac{n}{i}}) O(∑i=1nin⋅logp)=O(logp∑i=1nin)。
当积分算
∫
1
n
n
x
d
x
=
2
n
−
2
n
\int_1^n \sqrt{\dfrac{n}{x}}\, dx = 2n - 2\sqrt{n}
∫1nxndx=2n−2n
所以整个是 O ( n log p ) \Omicron(n\log p) O(nlogp) 的。
注意本题卡空间, μ \mu μ 数组的前缀和直接覆盖到 μ \mu μ 数组上即可。
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 = 104857601;
int p[MAXN / 10], mu[MAXN];
bool vis[MAXN];
void pre(int n)
{
mu[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!vis[i])
{
p[++p[0]] = i;
mu[i] = -1;
}
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++)
{
mu[i] = (mu[i - 1] + mu[i] + MOD - 1) % (MOD - 1);
}
}
int GetSum(int l, int r)
{
return (mu[r] - mu[l - 1] + MOD - 1) % (MOD - 1);
}
int block(int n)
{
int res = 0;
for (int l = 1, r; l <= n; l = r + 1)
{
int k = n / l;
r = n / k;
res = (res + (ll)GetSum(l, r) * k % (MOD - 1) * k % (MOD - 1)) % (MOD - 1);
}
return res;
}
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 main()
{
int n;
scanf("%d", &n);
pre(n);
int fac = 1;
for (int i = 1; i <= n; i++)
{
fac = (ll)fac * i % MOD;
}
fac = qpow(fac, 2 * n);
int ans = 1;
for (int i = 1; i <= n; i++)
{
ans = (ll)ans * qpow(i, block(n / i)) % MOD;
}
printf("%d\n", (ll)fac * inv((ll)ans * ans % MOD) % MOD);
return 0;
}