P5518 [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题
以下 \(/\) 表示下取整除法(时间复杂度除外),分数线才是真正的除法。
以下时间复杂度中的 \(n\) 表示 \(\max(A,B,C)\)。
对于不平常的柿子推导顺序,深感抱歉。
冗长の前置
0
注意别将 \(\sum\) 和 \(\prod\) 搞混,并且清楚他们的基础变换。
1
明白这个转换(\(f\) 为任意函数):
\[\begin{aligned}
\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\gcd(i,j,k)f(i,j,k)
&=\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}f(i,j,k)\sum_{d|i\ d|j\ d|k}\varphi(d)
\\
&=\sum_{d=1}^{\min(A,B,C)}\varphi(d)\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}\sum_{k=1}^{C/d}f(di,dj,dk)
\end{aligned}
\]
2
今天的 mvp 是(因为等会儿会用得多,先写上来):
\[mvp(n)=\sum_{d|n}d^{\mu(\frac{n}{d})}
\]
(没错起名就是这么随意)
她的前缀积预处理配合上整除分块可以 \(O(\sqrt n\log n)\) 解决这个问题(由对称性,不妨设 \(A\le B\);幂太长了,用 \(\text{pow}\) 代替):
\[\begin{aligned}
F(A,B)&=\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[\gcd(i,j)=1])
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}\sum_{x|i\ x|j}\mu(x))
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{x=1}^{A/d}\mu(x)(A/(xd))(B/(xd)))
\\&=\prod_{d=1}^A\prod_{x=1}^{A/d} \text{pow}(d,\mu(x)(A/(xd))(B/(xd)))
\\&=\prod_{T=1}^A\prod_{d|T} \text{pow}(d,\mu(\frac{T}{d})(A/T)(B/T))
\\&=\prod_{T=1}^A\left(\prod_{d|T} d^{\mu(\frac{T}{d})}\right)^{(A/T)(B/T)}
\\&=\prod_{T=1}^A mvp(T)^{(A/T)(B/T)}
\end{aligned}
\]
3
设 \(DC(n)=\frac{n(n+1)}{2}=1+\dots+n\)(Deng Cha)。
Mvp 的变形(机翻 deformation):
\[dmvp(n)=\left(\sum_{d|n}d^{\mu(\frac{n}{d})}\right)^{n^2}
\]
她很类似,前缀积预处理配合上整除分块可以 \(O(\sqrt n\log n)\) 解决下面这个问题(设 \(A\le B\)):
\[\begin{aligned}
G(A,B)&=\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}d^2ij[\gcd(i,j)=1])
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}d^2ij\sum_{x|i\ x|j}\mu(x))
\\&=\prod_{d=1}^A \text{pow}(d,\sum_{x=1}^{A/d}\mu(x)d^2x^2\sum_{i=1}^{A/xd}i\sum_{j=1}^{B/xd}j)
\\&=\prod_{d=1}^A\prod_{x=1}^{A/d} \text{pow}(d,\mu(x)(xd)^2 DC(A/xd)DC(B/xd))
\\&=\prod_{T=1}^A\prod_{d|T} \text{pow}(d,\mu(\frac{T}{d})T^2 DC(A/T)DC(B/T))
\\&=\prod_{T=1}^A dmvp(T)^{DC(A/T)DC(B/T)}
\end{aligned}
\]
简短の主干
看看我们要求的柿子:
\[\begin{aligned}
\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)^{f(type)}&=\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\left(\frac{ij}{\gcd(i,j)\gcd(i,k)}\right)^{f(type)}
\\&=\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}i^{f(type)}j^{f(type)}\gcd(i,j)^{-f(type)}\gcd(i,k)^{-f(type)}
\end{aligned}
\]
所以说我们转化成了两个子问题:
\[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}i^{f(type)}
\quad
\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\gcd(i,j)^{f(type)}
\]
type=0
\[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}i=(A!)^{BC}
\]
\[\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=F(A,B)^C
\]
type=1
\[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}i^{ijk}=\left(\prod_{i=1}^{A}i^i\right)^{DC(j)DC(k)}
\]
里面的连乘预处理即可。
\[\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)^{DC(C)}=G(A,B)^{DC(C)}
\]
type=2
注意到原柿子
\[\begin{aligned}
\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)^{\gcd(i,j,k)}&=\exp\ln\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)^{\gcd(i,j,k)}
\\&=\exp\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\gcd(i,j,k)\ln\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)
\\&=\exp\sum_{d=1}^{\min(A,B,C)}\varphi(d)\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}\sum_{k=1}^{C/d}\ln\left(\frac{\text{lcm}(di,dj)}{\gcd(di,dk)}\right)
\\&=\exp\sum_{d=1}^{\min(A,B,C)}\varphi(d)\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}\sum_{k=1}^{C/d}\ln\left(\frac{\text{lcm}(i,j)}{\gcd(i,k)}\right)
\\&=\prod_{d=1}^{\min(A,B,C)}\text{work}_{type=0}(A/d,B/d,C/d)^{\varphi(d)}
\end{aligned}
\]
所以就转化成了 type=0 的情形。
难算の时间
首先预处理是 \(O(n\log n)\) 的,因为有逆元。
type=0 和 type=1 均是 \(O(T\sqrt n\log n)\) 的,已经说过。
type=2 调用了 type=0,较为难算(以下比较符号均代表 \(O\) 的比较):
\[\begin{aligned}
Time&\le\sum_{i=1}^{\sqrt n}\sqrt i\log i+\sum_{i=1}^{\sqrt n}\sqrt \frac{n}{i}\log \frac{n}{i}
\\&=\int_1^{\sqrt n}\sqrt x\log x\, \text{d}x+\int_1^{\sqrt n}\sqrt\frac{n}{x}\log \frac{n}{x}\, \text{d}x
\\&\le \log n\int_1^{\sqrt n}\sqrt x\, \text{d}x+\sqrt n\log n\int_1^{\sqrt n}\sqrt\frac{1}{x}\, \text{d}x
\\&= \log n\ x^{3/2}|_{1}^{\sqrt n}+\sqrt n\log n\ x^{1/2}|_{1}^{\sqrt n}
\\&=n^{3/4} \log n+n^{3/4} \log n
\\&=n^{3/4} \log n
\end{aligned}
\]
所以总时间 \(O(n\log n+Tn^{3/4}\log n)\)。
条理の代码
//We'll be counting stars.
#include<bits/stdc++.h>
using namespace std;
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
#define int long long
const int N=100000,M=100001;//number, memory
int mod,phi[M],mu[M],f[M],mp[M],mvp[M],imvp[M],dmvp[M],idmvp[M];
bool vis[M];
vector<int> p;
inline int pw(int x,int y){int r=1;while(y){if(y&1)r=r*x%mod;x=x*x%mod;y>>=1;}return r;}
inline int inv(int x){ return pw(x,mod-2); }
void init(){
p.reserve(9593);
phi[1]=mu[1]=1;
For(i,2,N){
if(!vis[i]){
p.emplace_back(i);
phi[i]=i-1,mu[i]=-1;
}
for(int j:p){
if(i*j>=N) break;
vis[i*j]=1;
if(i%j==0){
phi[i*j]=phi[i]*j,mu[i*j]=0;
break;
}else{
phi[i*j]=phi[i]*(j-1),mu[i*j]=-mu[i];
}
}
}
For(i,1,N) phi[i]+=phi[i-1];
f[0]=1; For(i,1,N) f[i]=f[i-1]*i%mod;
mp[0]=1; For(i,1,N) mp[i]=mp[i-1]*pw(i,i)%mod;
fill(mvp+1,mvp+N,1);
int x;
For(i,1,N){
x=inv(i);
For(j,1,N/i)
if(mu[j]==1) (mvp[i*j]*=i)%=mod;
else if(mu[j]==-1) (mvp[i*j]*=x)%=mod;
}
For(i,1,N) dmvp[i]=pw(mvp[i],i*i%(mod-1));
mvp[0]=dmvp[0]=1;
For(i,1,N) (mvp[i]*=mvp[i-1])%=mod;
For(i,0,N) imvp[i]=inv(mvp[i]);
For(i,1,N) (dmvp[i]*=dmvp[i-1])%=mod;
For(i,0,N) idmvp[i]=inv(dmvp[i]);
}
inline int DC(int x){ return x*(x+1)/2%(mod-1); }
inline int F(int A,int B){
if(A>B) swap(A,B);
int ans=1;
for(int l=1,r;l<=A;l=r+1){
r=min(A/(A/l),B/(B/l));
(ans*=pw(mvp[r]*imvp[l-1]%mod,(A/l)*(B/l)%(mod-1)))%=mod;
}
return ans;
}
inline int G(int A,int B){
if(A>B) swap(A,B);
int ans=1;
for(int l=1,r;l<=A;l=r+1){
r=min(A/(A/l),B/(B/l));
(ans*=pw(dmvp[r]*idmvp[l-1]%mod,DC(A/l)*DC(B/l)%(mod-1)))%=mod;
}
return ans;
}
int work0(int A,int B,int C){
return pw(pw(f[A],B)*pw(f[B],A)%mod,C)*
inv(pw(F(A,B),C)*pw(F(A,C),B)%mod)%mod;
}
int work1(int A,int B,int C){
return pw(pw(mp[A],DC(B))*pw(mp[B],DC(A))%mod,DC(C))*
inv(pw(G(A,B),DC(C))*pw(G(A,C),DC(B))%mod)%mod;
}
int work2(int A,int B,int C){
int ans=1,lim=min({A,B,C});
for(int l=1,r;l<=lim;l=r+1){
r=min({A/(A/l),B/(B/l),C/(C/l)});
(ans*=pw(work0(A/l,B/l,C/l),(phi[r]-phi[l-1])%(mod-1)))%=mod;
}
return ans;
}
signed main(){
int T,A,B,C;
scanf("%lld%lld",&T,&mod);
init();
while(T--){
scanf("%lld%lld%lld",&A,&B,&C);//A,B,C of 'work*()' CANNOT exchange!!!
printf("%lld %lld %lld\n",work0(A,B,C),work1(A,B,C),work2(A,B,C));
}
return 0;}