/youl 乐团 题解

P5518 [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题

以下 / 表示下取整除法(时间复杂度除外),分数线才是真正的除法。

以下时间复杂度中的 n 表示 max(A,B,C)

对于不平常的柿子推导顺序,深感抱歉。

冗长の前置

0

注意别将 搞混,并且清楚他们的基础变换。

1

明白这个转换(f 为任意函数):

i=1Aj=1Bk=1Cgcd(i,j,k)f(i,j,k)=i=1Aj=1Bk=1Cf(i,j,k)d|i d|j d|kφ(d)=d=1min(A,B,C)φ(d)i=1A/dj=1B/dk=1C/df(di,dj,dk)

2

今天的 mvp 是(因为等会儿会用得多,先写上来):

mvp(n)=d|ndμ(nd)

(没错起名就是这么随意)

她的前缀积预处理配合上整除分块可以 O(nlogn) 解决这个问题(由对称性,不妨设 AB;幂太长了,用 pow 代替):

F(A,B)=i=1Aj=1Bgcd(i,j)=d=1Apow(d,i=1A/dj=1B/d[gcd(i,j)=1])=d=1Apow(d,i=1A/dj=1B/dx|i x|jμ(x))=d=1Apow(d,x=1A/dμ(x)(A/(xd))(B/(xd)))=d=1Ax=1A/dpow(d,μ(x)(A/(xd))(B/(xd)))=T=1Ad|Tpow(d,μ(Td)(A/T)(B/T))=T=1A(d|Tdμ(Td))(A/T)(B/T)=T=1Amvp(T)(A/T)(B/T)

3

DC(n)=n(n+1)2=1++n(Deng Cha)。

Mvp 的变形(机翻 deformation):

dmvp(n)=(d|ndμ(nd))n2

她很类似,前缀积预处理配合上整除分块可以 O(nlogn) 解决下面这个问题(设 AB):

G(A,B)=i=1Aj=1Bgcd(i,j)ij=d=1Apow(d,i=1A/dj=1B/dd2ij[gcd(i,j)=1])=d=1Apow(d,i=1A/dj=1B/dd2ijx|i x|jμ(x))=d=1Apow(d,x=1A/dμ(x)d2x2i=1A/xdij=1B/xdj)=d=1Ax=1A/dpow(d,μ(x)(xd)2DC(A/xd)DC(B/xd))=T=1Ad|Tpow(d,μ(Td)T2DC(A/T)DC(B/T))=T=1Admvp(T)DC(A/T)DC(B/T)

简短の主干

看看我们要求的柿子:

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))f(type)=i=1Aj=1Bk=1C(ijgcd(i,j)gcd(i,k))f(type)=i=1Aj=1Bk=1Cif(type)jf(type)gcd(i,j)f(type)gcd(i,k)f(type)

所以说我们转化成了两个子问题:

i=1Aj=1Bk=1Cif(type)i=1Aj=1Bk=1Cgcd(i,j)f(type)

type=0

i=1Aj=1Bk=1Ci=(A!)BC

i=1Aj=1Bk=1Cgcd(i,j)=(i=1Aj=1Bgcd(i,j))C=F(A,B)C

type=1

i=1Aj=1Bk=1Ciijk=(i=1Aii)DC(j)DC(k)

里面的连乘预处理即可。

i=1Aj=1Bk=1Cgcd(i,j)ijk=(i=1Aj=1Bgcd(i,j)ij)DC(C)=G(A,B)DC(C)

type=2

注意到原柿子

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))gcd(i,j,k)=explni=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))gcd(i,j,k)=expi=1Aj=1Bk=1Cgcd(i,j,k)ln(lcm(i,j)gcd(i,k))=expd=1min(A,B,C)φ(d)i=1A/dj=1B/dk=1C/dln(lcm(di,dj)gcd(di,dk))=expd=1min(A,B,C)φ(d)i=1A/dj=1B/dk=1C/dln(lcm(i,j)gcd(i,k))=d=1min(A,B,C)worktype=0(A/d,B/d,C/d)φ(d)

所以就转化成了 type=0 的情形。

难算の时间

首先预处理是 O(nlogn) 的,因为有逆元。

type=0 和 type=1 均是 O(Tnlogn) 的,已经说过。

type=2 调用了 type=0,较为难算(以下比较符号均代表 O 的比较):

Timei=1nilogi+i=1nnilogni=1nxlogxdx+1nnxlognxdxlogn1nxdx+nlogn1n1xdx=logn x3/2|1n+nlogn x1/2|1n=n3/4logn+n3/4logn=n3/4logn

所以总时间 O(nlogn+Tn3/4logn)

条理の代码

//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;}
posted @   ShaoJia  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示