【题解】Luogu P5518 题解
Description
令:
\[f(\textit{type})=\begin{cases}1&\textit{type}=0\\ijk&\textit{type}=1\\\gcd(i,j,k)&\textit{type}=2\end{cases} \]给定 \(A,B,C\),求:
\[\textit{ans}_{\textit{type}}=\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{\operatorname{lcm}(i,j)}{\gcd(i,k)}\right)^{f(\textit{type})} \]多测,对给定质数 \(p\) 取模。
\(1\le A,B,C\le 10^5\),\(10^7\le p\le 1.05\times10^9,p\in\mathbb{P}\),\(T=70\)。
Solution
首先对原式化简一下:
\[\begin{aligned}
\textit{ans}_{\textit{type}}=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{\operatorname{lcm}(i,j)}{\gcd(i,k)}\right)^{f(\textit{type})}\\
=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{ij}{\gcd(i,j)\cdot\gcd(i,k)}\right)^{f(\textit{type})}
\end{aligned}
\]
于是原式可以分为两个部分:
\[\begin{aligned}
& \mathcal F(A,B,C) = \prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{f(\textit{type})}\\
& \mathcal G(A,B,C)=\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{f(\textit{type})}
\end{aligned}
\]
显然有:
\[\textit{ans}_{\textit{type}}=\frac{\mathcal F(A,B,C)\cdot\mathcal F(B,A,C)}{\mathcal G(A,B,C)\cdot\mathcal G(A,C,B)}
\]
接下来就开始推柿子吧!
\(\textit{type}=0\)
\[\begin{aligned}
\mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci\\
=&\prod_{i=1}^A\prod_{j=1}^Bi^C\\
=&\prod_{i=1}^Ai^{B\cdot C}\\
=&(A!)^{B\cdot C}
\end{aligned}
\]
预处理阶乘,每次计算快速幂即可。
\[\begin{aligned}
\mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)\\
=&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)\right)^C\\
\end{aligned}
\]
然后开始莫反:
\[\begin{aligned}
\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)=&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^Bd^{[\gcd(i,j)=d]}\\
=&\prod_{d=1}\prod_{i=1}^{\lfloor \frac Ad\rfloor}\prod_{j=1}^{\lfloor\frac Bd\rfloor}d^{[gcd(i,j)=1]}\\
=&\prod_{d=1}d^{\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[gcd(i,j)=1]}
\end{aligned}
\]
把指数提出来推一下:
\[\begin{aligned}
\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[gcd(i,j)=1]=&\sum_{e=1}\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[e\mid i][e \mid j]\mu(e)\\
=&\sum_{e=1}\sum_{i=1}^{\lfloor \frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}\mu(e)\\
=&\sum_{e=1}\lfloor \frac A{de}\rfloor\lfloor\frac B{de}\rfloor\mu(e)
\end{aligned}
\]
带回去就有:
\[\begin{aligned}
\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)=&\prod_{d=1}d^{\sum_{e=1}\lfloor \frac A{de}\rfloor\lfloor\frac B{de}\rfloor\mu(e)}\\
=&\prod_{t=1}\prod_{d\mid t}d^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor\mu(\frac td)}\\
=&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
\mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)\\
=&\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\right)^C\\
\end{aligned}
\]
最里面括号内的东西可以用类似埃氏筛的方法预处理一下,即对于每个 \(d\),将它的贡献累乘到它的每个倍数上。预处理完成后就可以快乐的整除分块了。
\(\textit{type}=1\)
定义:\(S(n)=\sum_{i=1}^ni=\frac{n(n+1)}2\)。
然后开始推柿子:
\[\begin{aligned}
\mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{ijk}\\
=&\left(\prod_{i=1}^A\prod_{j=1}^Bi^{ij}\right)^{S(C)}\\
=&\left(\prod_{i=1}^Ai^i\right)^{S(B)\cdot S(C)}
\end{aligned}
\]
预处理 \(\prod_{i=1}^Ai^i\) 即可。
\[\begin{aligned}
\mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{ijk}\\
=&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}\right)^{S(C)}\\
\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}=&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^Bd^{[\gcd(i,j)=d]ij}\\
=&\prod_{d=1}\prod_{i=1}^{\lfloor\frac Ad\rfloor}\prod_{j=1}^{\lfloor\frac Bd\rfloor}d^{[\gcd(i,j)=1]ijd^2}\\
=&\prod_{d=1}d^{d^2\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[\gcd(i,j)=1]ij}
\end{aligned}
\]
把指数拎出来:
\[\begin{aligned}
\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[\gcd(i,j)=1]ij=&\sum_{e=1}\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[e\mid i][e\mid j]\mu(e)ij\\
=&\sum_{e=1}\sum_{i=1}^{\lfloor\frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}e^2\mu(e)ij\\
=&\sum_{e=1}e^2\mu(e)\left(\sum_{i=1}^{\lfloor\frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}ij\right)\\
=&\sum_{e=1}e^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor)
\end{aligned}
\]
带回去:
\[\begin{aligned}
\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}=&\prod_{d=1}d^{d^2\sum_{e=1}e^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor)}\\
=&\prod_{e=1}\prod_{d=1}d^{(de)^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor)}\\
=&\prod_{t=1}\prod_{d\mid t}d^{t^2\mu(\frac td)S(\lfloor\frac A{t}\rfloor)S(\lfloor\frac B{t}\rfloor)}\\
=&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{t^2S(\lfloor\frac At\rfloor)S(\lfloor\frac Bt\rfloor)}\\
\mathcal G(A,B,C)=&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}\right)^{S(C)}\\
=&\left(\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{t^2}\right)^{S(\lfloor\frac At\rfloor)S(\lfloor\frac Bt\rfloor)}\right)^{S(C)}
\end{aligned}
\]
括号里的东西其实就是第一问预处理的那个东西的 \(t^2\) 次方,预处理一下即可整除分块。
\(\textit{type}=2\)
毒瘤。
\[\begin{aligned}
\mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{\gcd(i,j,k)}\\
=&\prod_{i=1}^Ai^{\sum_{j=1}^B\sum_{k=1}^C\gcd(i,j,k)}\\
=&\prod_{d=1}\prod_{i=1}^Ai^{\sum_{j=1}^B\sum_{k=1}^C[\gcd(i,j,k)=d]d}\\
=&\prod_{d=1}\prod_{i=1}^{\lfloor\frac Ad\rfloor}(id)^{\sum_{j=1}^{B/d}\sum_{k=1}^{C/d}[\gcd(i,j,k)=1]d}\\
=&\prod_{d=1}\prod_{e=1}\prod_{i=1}^{\lfloor\frac A{de}\rfloor}(ide)^{\lfloor{\frac B{de}}\rfloor\lfloor{\frac C{de}}\rfloor\mu(e)d}\\
=&\prod_{t=1}\prod_{d\mid t}\prod_{i=1}^{\lfloor\frac At\rfloor}(it)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor\mu(\frac td)d}\\
=&\prod_{t=1}\left(\prod_{d\mid t}\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\mu(\frac td)d}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\
=&\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\sum_{d\mid t}\mu(\frac td)d}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\
=&\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\varphi(t)}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\
\end{aligned}
\]
这玩意有点复杂,把它拆成两个部分:
\[\begin{aligned}
& f_0(A,B,C)=\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\right)^{\varphi(t)}\\
& f_1(A,B,C)=\prod_{t=1}\left(t^{\varphi(t)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}
\end{aligned}
\]
\(f_1\) 可以整除分块了,把 \(f_2\) 先放着,看 \(\mathcal G\):
\[\begin{aligned}
\mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{\gcd(i,j,k)}\\
=&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Cd^{[\gcd(i,j)=d]\gcd(d,k)}\\
=&\prod_{d=1}d^{\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[\gcd(i,j)=1]\sum_{k=1}^C\gcd(d,k)}\\
=&\prod_{d=1}d^{\sum_{e=1}\lfloor{\frac A{de}\rfloor}\lfloor\frac B{de}\rfloor\mu(e)\cdot\sum_{k=1}^C\gcd(d,k)}\\
=&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)\cdot\sum_{k=1}^C\gcd(d,k)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}
\end{aligned}
\]
指数上的东西:
\[\begin{aligned}
\sum_{k=1}^C\gcd(d,k)=&\sum_{f\mid d}\sum_{k=1}^{\lfloor\frac Cf\rfloor}[\gcd(\frac df,k)=1]f\\
=&\sum_{f\mid d}\sum_{g\mid\frac df}\lfloor\frac C{fg}\rfloor\mu(g)f\\
=&\sum_{u\mid d}\varphi(u)\lfloor\frac Cu\rfloor
\end{aligned}
\]
然后带回去:
\[\begin{aligned}
\mathcal G(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)\sum_{u\mid d}\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
\end{aligned}
\]
这玩意不怎么好预处理。考虑把底数的 \(d\) 拆成 \(u\) 和 \(\frac du\):
\[\begin{aligned}
& g_0(A,B,C)=\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
& g_1(A,B,C)=\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}
\end{aligned}
\]
分别推一下:
\[\begin{aligned}
g_0(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
=&\prod_{t=1}\left(\prod_{u\mid t}\prod_{u\mid d\mid t}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
=&\prod_{t=1}\left(\prod_{u\mid t}\left(\prod_{d\mid \frac tu}d^{\mu(\frac td)}\right)^{\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
=&\prod_{u=1}\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\right)^{\varphi(u)\lfloor\frac Cu\rfloor}
\end{aligned}
\]
括号里的东西预处理过了,两次整除分块可以搞定。
\[\begin{aligned}
g_1(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\
=&\prod_{u=1}\prod_{t=1}\left(\prod_{d\mid t}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\\
=&\prod_{u=1}u^{\sum_{t=1}\sum_{d\mid t}\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\\
=&\prod_{u=1}u^{\varphi(u)\lfloor\frac Cu\rfloor\sum_{t=1}\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor\sum_{d\mid t}\mu(\frac td)}\\
=&\prod_{u=1}u^{\varphi(u)\lfloor\frac Cu\rfloor\sum_{t=1}\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor[t=1]}\\
=&\prod_{u=1}u^{\varphi(u)\lfloor\frac Au\rfloor\lfloor\frac Bu\rfloor\lfloor\frac Cu\rfloor}\\
\end{aligned}
\]
注意到,\(g_1\) 和之前的 \(f_1\) 其实是一样的,而且它们的值不受 \(A,B,C\) 顺序的影响,因此可以把它们约掉。
卡常小技巧(不过应该众所周知):把预处理的东西的逆元同时预处理出来可以大幅减小常数
code:
#include <cstdio>
const int N = 1e5,maxn = N + 5;
int T,p,phi,A,B,C,ta,tb,tc;
int pri[maxn],mu[maxn],Inv[maxn],f[maxn],Phi[maxn];
int fac[maxn],fd[maxn],facInv[maxn],fdInv[maxn];
int Fac[maxn],Fd[maxn],FdInv[maxn],ps[maxn];
bool isp[maxn];
inline int read() {
#define gc c = getchar()
int d = 0,f = 0,gc;
for(;c < 48 || c > 57;gc) f |= (c == '-');
for(;c > 47 && c < 58;gc) d = (d << 1) + (d << 3) + (c ^ 48);
#undef gc
return f ? -d : d;
}
inline int Mul(int a,int b,int mod) { return 1LL * a * b % mod; }
inline int Add(int a,int b,int mod) { a += b; return a > mod ? a - mod : a; }
inline int max(int a,int b) { return a > b ? a : b; }
inline int min(int a,int b) { return a < b ? a : b; }
inline int min(int a,int b,int c) { return min(min(a,b),c); }
inline int fpow(int a,int b,int mod) {
int res = 1;
for(;b;a = Mul(a,a,mod),b >>= 1) if(b & 1) res = Mul(res,a,mod);
return res;
}
inline int GetInv(int a) { return a <= N ? Inv[a] : fpow(a,p - 2,p); }
namespace Type0 {
inline int F(int A,int B,int C) { return fpow(fac[A],Mul(B,C,phi),p); }
inline int G(int A,int B,int C) {
int res,ans = 1;
for(int r,l = 1;l <= A && l <= B;l = r + 1) {
ta = A / l,tb = B / l; r = min(A / ta,B / tb);
res = Mul(fd[r],fdInv[l - 1],p);
ans = Mul(ans,fpow(res,Mul(ta,tb,phi),p),p);
}
return fpow(ans,C,p);
}
inline int solve() {
int res = Mul(F(A,B,C),F(B,A,C),p);
int inv = Mul(G(A,B,C),G(A,C,B),p);
return Mul(res,GetInv(inv),p);
}
}
namespace Type1 {
inline int S(int n) { return 1LL * n * (n + 1) / 2 % phi; }
inline int F(int A,int B,int C) { return fpow(Fac[A],Mul(S(B),S(C),phi),p); }
inline int G(int A,int B,int C) {
int res,ans = 1;
for(int r,l = 1;l <= A && l <= B;l = r + 1) {
ta = A / l,tb = B / l;
r = min(A / ta,B / tb);
res = Mul(Fd[r],FdInv[l - 1],p);
ans = Mul(ans,fpow(res,Mul(S(ta),S(tb),phi),p),p);
}
return fpow(ans,S(C),p);
}
inline int solve() {
int res = Mul(F(A,B,C),F(B,A,C),p);
int inv = Mul(G(A,B,C),G(A,C,B),p);
return Mul(res,GetInv(inv),p);
}
}
namespace Type2 {
inline int F(int A,int B,int C) {
int exp,res,ans = 1;
for(int r,l = 1;l <= min(A,B,C);l = r + 1) {
ta = A / l,tb = B / l,tc = C / l;
r = min(A / ta,B / tb,C / tc);
exp = Add(ps[r],phi - ps[l - 1],phi);
res = fpow(fac[ta],Mul(tb,tc,phi),p);
ans = Mul(ans,fpow(res,exp,p),p);
}
return ans;
}
inline int g0(int A,int B) {
int res,ans = 1;
for(int r,l = 1;l <= A && l <= B;l = r + 1) {
ta = A / l,tb = B / l;
r = min(A / ta,B / tb);
res = Mul(fd[r],fdInv[l - 1],p);
ans = Mul(ans,fpow(res,Mul(ta,tb,phi),p),p);
}
return ans;
}
inline int G(int A,int B,int C) {
int res,ans = 1;
for(int r,l = 1;l <= min(A,B,C);l = r + 1) {
ta = A / l,tb = B / l,tc = C / l;
r = min(A / ta,B / tb,C / tc);
res = fpow(g0(ta,tb),tc,p);
ans = Mul(ans,fpow(res,Add(ps[r],phi - ps[l - 1],phi),p),p);
}
return ans;
}
inline int solve() {
int res = Mul(F(A,B,C),F(B,A,C),p);
int inv = Mul(G(A,B,C),G(A,C,B),p);
return Mul(res,GetInv(inv),p);
}
}
inline void Init() {
mu[1] = Phi[1] = f[1] = Inv[0] = Inv[1] = 1;
fac[0] = fac[1] = Fac[0] = facInv[0] = 1;
fd[0] = Fd[0] = fdInv[0] = FdInv[0] = 1;
for(int i = 2;i <= N;i ++) {
f[i] = 1,fac[i] = Mul(i,fac[i - 1],p);
if(!isp[i]) pri[++ pri[0]] = i,mu[i] = -1,Phi[i] = i - 1;
for(int j = 1;j <= pri[0] && i * pri[j] <= N;j ++) {
isp[i * pri[j]] = true;
if(!(i % pri[j])) {
mu[i * pri[j]] = 0;
Phi[i * pri[j]] = Phi[i] * pri[j];
break;
}
mu[i * pri[j]] = -mu[i];
Phi[i * pri[j]] = Phi[i] * Phi[pri[j]];
}
}
facInv[N] = fpow(fac[N],p - 2,p);
for(int i = N - 1;i;i --) {
facInv[i] = Mul(facInv[i + 1],i + 1,p);
Inv[i + 1] = Mul(facInv[i + 1],fac[i],p);
}
for(int i = 1;i <= N;i ++) {
ps[i] = Add(Phi[i],ps[i - 1],phi);
Fac[i] = Mul(Fac[i - 1],fpow(i,i,p),p);
fd[i] = Mul(f[i],fd[i - 1],p);
Fd[i] = Mul(fpow(f[i],Mul(i,i,phi),p),Fd[i - 1],p);
fdInv[i] = GetInv(fd[i]),FdInv[i] = GetInv(Fd[i]);
if(!mu[i]) continue;
for(int j = 1;i * j <= N;j ++)
f[i * j] = Mul(f[i * j],mu[i] == 1 ? j : Inv[j],p);
}
}
int main() {
T = read(),p = read();
phi = p - 1; Init();
for(;T;T --) {
A = read(),B = read(),C = read();
printf("%d %d %d\n",Type0::solve(),Type1::solve(),Type2::solve());
}
return 0;
}