题解P5221 Product
这题好像可以用莫反做,但数论分块似乎会被卡
\[\prod_{i=1}^n\prod_{j=1}^n\frac{lcm(i,j)}{gcd(i,j)}=\prod_{i=1}^n\prod_{j=1}^n\frac{ij}{gcd(i,j)^2}\\=\prod_{i=1}^n\prod_{j=1}^nij\times\prod_{i=1}^n\prod_{j=1}^ngcd(i,j)^{-2}
\]
首先看 \(\prod\limits_{i=1}^n\prod\limits_{j=1}^nij\)
\[=\prod_{i=1}^ni^n\prod_{j=1}^nj=\prod_{i=1}^ni^nn!=(n!)^n\times(n!)^n=(n!)^{2n}
\]
接着尝试化简一下后面那一坨
\[\prod_{i=1}^n\prod_{j=1}^ngcd(i,j)=\prod_{d=1}^nd^{\sum\limits_{i=1}^n\sum\limits_{j=1}^n[gcd(i,j)=d]}\\=\prod_{d=1}^nd^{\sum\limits_{i=1}^{\frac{n}{d}}\sum\limits_{j=1}^{\frac{n}{d}}[gcd(i,j)=1]}
\]
仔细观察一下指数,发现可以用莫反加数论分块,但时间复杂度就是 \(O(n\sqrt{n})\), 有点勉强,所以可以考虑欧拉函数 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^i[gcd(i,j)=1]=\sum\limits_{i=1}^n\phi(i)\)
令 \(sum(n)=\sum\limits_{i=1}^n\phi(i)\) 那么上述式子的指数 \(=2\times sum(\lfloor\frac{n}{d}\rfloor)-1\)
\[\Rightarrow ans=(n!)^{2n}\times\prod_{d=1}^nd^{2\times sum(\lfloor\frac{n}{d}\rfloor)-1}
\]
因为此题卡空间,数组不能开long long,所以需要用到欧拉定理 \(a^c\equiv a^{c~mod~\phi(m)}(mod~m)\), 这样就不需要开long long了
代码
#include<iostream>
#include<cstdio>
#define MOD (104857601)
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
bool st[N];
int phi[N], prime[N], tot;
void init()
{
phi[1] = 1;
for (int i = 2; i < N; i++)
{
if (!st[i])
prime[++tot] = i, phi[i] = i - 1;
for (int j = 1; i * prime[j] < N; j++)
{
st[i * prime[j]] = true;
if (i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
for (int i = 1; i < N; i++)
phi[i] = (phi[i] + phi[i - 1]) % (MOD - 1);
}
int qmi(int a, ll b)
{
int res = 1;
while (b)
{
if (b & 1)
res = (ll)res * a % MOD;
a = (ll)a * a % MOD;
b >>= 1;
}
return res;
}
int main()
{
init();
int n;
scanf("%d", &n);
int ans = 1;
for (int i = 1; i <= n; i++)
ans = (ll)ans * i % MOD;
ans = qmi(ans, 2 * n);
int temp = 1;
for (int i = 2; i <= n; i++)
temp = (ll)temp * qmi(i, 2 * phi[n / i] - 1) % MOD;
temp = (ll)temp * temp % MOD;
temp = qmi(temp, MOD - 2);
printf("%d", (ll)temp * ans % MOD);
return 0;
}