Loading

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

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

    看完数据范围(\(T=70\))大概是对于每个 \(type\) 做到 \(O(n)\) 以内。

    type=0

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\dfrac{\operatorname{lcm(i,j)}}{\gcd(i,k)}\\ =\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\dfrac{i\times j}{\gcd(i,j)\times \gcd(i,k)}\\ \]

    分母:

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\gcd(i,j)\\ =(\prod_{d=1}^{A}d^{\sum_{i=1}^{A}\sum_{j=1}^{B}[\gcd(i,j)==d]})^C\\ =(\prod_{d=1}^{A}d^{f(\frac{n}{d},\frac{m}{d})})^C \]

    其中

    \[f(n,m)=\sum_{i=1}^{n} \sum_{j=1}^{m}[gcd(i,j)==1]\\ =\sum_{x=1}^{n}\mu(x)\frac{n}{x}\dfrac{m}{x} \]

    \(2\) 层整除分块就可以 \(O(n+\sqrt{n}\log n)\) 了。

    分子:

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}ij\\ =(\prod_{i=1}^{A}\prod_{j=1}^{B}ij)^C\\ =((A!)^{B}\times(B!)^{A})^C \]

    预处理阶乘可 \(O(\log n)\) 计算。

    type=1

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}(\dfrac{i\times j}{\gcd(i,j)\times \gcd(i,k)})^{ijk}\\ \]

    分子:

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}(ij)^{ijk}\\ =(\prod_{i=1}^{A}(i^i)^{1+2+\cdots A}\prod_{j=1}^{B}(j^j)^{1+2+\cdots+A})^{1+2+\cdots+C}\\ \]

    \(jp_n=\prod_{i=1}^{n}i^i\) (快速幂预处理),则原式

    \[=((jp_A)^{1+2+\cdots+B}(jp_B)^{1+2+\cdots+A})^{1+2+\cdots+C}\\ =((jp_A)^{B\times(B+1)/2} \times (jp_B)^{A\times(A+1)/2})^{C\times(C+1)/2} \]

    分母:

    \[\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\gcd(i,j)^{ijk}\\ =(\prod_{i=1}^{A}\prod_{j=1}^{B}\gcd(i,j)^{ij})^{C\times(C+1)/2}\\ =(\prod_{d=1}^{A}d^{f(A,B,d)})^{C\times(C+1)/2}\\ \]

    其中

    \[f(n,m,d)=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)==d]ij\\ =d^2\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{m}{d}}[\gcd(i,j)==1]ij\\ =d^2\sum_{x=1}^{\frac{n}{d}}\mu(x)x^2\sum_{i=1}^{\frac{n}{dx}}\sum_{j=1}^{\frac{m}{dx}}ij\\ \]

    带回原式换个写法

\[ =(\prod_{d=1}^{A}d^{f(A,B,d)})^{C\times(C+1)/2}\\=(\prod_{d=1}^{A}d^{g(\frac{A}{d},\frac{B}{d})*d^2})^{C\times(C+1)/2}\\=(\prod_{d=1}^{A}(d^{(d^2)})^{g(\frac{A}{d},\frac{B}{d})})^{C\times(C+1)/2} \]

其中

\[ g(n,m)=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)==1]ij \]

快速幂预处理 \(d^{(d^2)}\) 就可以整除分块套整除分块 \(O(n)\)

type=2

请确认您掌握狄利克雷卷积,这部分大量运用狄利克雷卷积来化简式子

\[ \prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}(\dfrac{i\times j}{\gcd(i,j)\times \gcd(i,k)})^{\gcd(i,j,k)}\\ \]

分子:

\[ \prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}i^{\gcd(i,j,k)}\\ =\prod_{d=1}^{A}\prod_{i=1}^{\frac{A}{d}}(id)^{\sum_{j=1}^{B}\sum_{k=1}^{C}{[\gcd(i,j,k)==d}]d}\\ =\prod_{d=1}^{A}\prod_{i=1}^{\frac{A}{d}}(id)^{\sum_{j=1}^{\frac{B}{d}}\sum_{k=1}^{\frac{C}{d}}{[\gcd(i,j,k)==1}]d}\\ =\prod_{d=1}^{A}\prod_{i=1}^{\frac{A}{d}}(id)^{\sum_{j=1}^{\frac{B}{d}}\sum_{k=1}^{\frac{C}{d}}\sum_{x|\gcd(i,j,k)}\mu(x)d}\\ =\prod_{d=1}^{A}\prod_{x=1}^{\frac{A}{d}}\prod_{i=1}^{\frac{A}{dx}}(idx)^{\mu(x)d\frac{B}{dx}\frac{C}{dx}}\\ =\prod_{T=1}^{A}\prod_{d|T}^{}\prod_{i=1}^{\frac{A}{T}}(iT)^{\mu(\frac{T}{d})d\frac{B}{T}\frac{C}{T}}\\ \]

注意到指数有一个 \(\sum_{d|T}\mu(\dfrac{T}{d})d=\mu*I=\varphi\)

\[ \prod_{T=1}^{A}\prod_{d|T}^{}\prod_{i=1}^{\frac{A}{T}}(iT)^{\mu(\frac{T}{d})d\frac{B}{T}\frac{C}{T}}\\ =\prod_{T=1}^{A}\prod_{i=1}^{\frac{A}{T}}(iT)^{\varphi(T)\frac{B}{T}\frac{C}{T}}\\ =\prod_{T=1}^{A}(jc_{\frac{A}{T}}T^{\frac{A}{T}})^{\varphi(T)\frac{B}{T}\frac{C}{T}}\\ \]

预处理 \(T^{\varphi(T)}\) 的前缀积和 \(\sum\varphi(i) \% (mod-1)\) 整除分块即可。

分母:

\[ \prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}\gcd(i,j)^{\gcd(i,j,k)}\\ =\prod_{d=1}^{A}\prod_{i=1}^{A}\prod_{j=1}^{B}\prod_{k=1}^{C}[\gcd(i,j)==d]d^{\gcd(d,k)}\\ =\prod_{d=1}^{A}d^{\sum_{i=1}^{A}\sum_{j=1}^{B}[\gcd(i,j)==d]\sum_{k=1}^{C}\gcd(d,k)}\\ =\prod_{d=1}^{A}d^{\sum_{x=1}^{\frac{A}{d}}\mu(x)\frac{A}{dx}\frac{B}{dx}\sum_{k=1}^{C}\gcd(d,k)}\\ =\prod_{d=1}^{A}d^{\sum_{T=1,d|T}^{A}\mu(\frac{T}{d})\frac{A}{T}\frac{B}{T}\sum_{k=1}^{C}\gcd(d,k)}\\ \]

单独提出后一部分来算。

\[ \sum_{k=1}^{C}\gcd(d,k)\\ =\sum_{x|d}\sum_{k=1}^{C}[\gcd(d,k)==x]x\\ =\sum_{x|d}x\sum_{k=1}^{\frac{C}{x}}[\gcd(\dfrac{d}{x},k)==1]\\ =\sum_{x|d}x\sum_{k=1}^{\frac{C}{x}}\sum_{t|\gcd(\frac{d}{x},k)}\mu(t)\\ =\sum_{x|d}x\sum_{t=1}^{\frac{C}{x}}\mu(t)\dfrac{C}{tx}\\ =\sum_{x|d}x\sum_{T=1,x|T}^{C}\mu(\dfrac{T}{x})\dfrac{C}{T}\\ =\sum_{T=1,T|d}^{C}\dfrac{C}{T}\sum_{x|T}x\mu(\dfrac{T}{x})\\ =\sum_{T|d}\varphi(T)\dfrac{C}{T} \]

带回去

\[ =\prod_{d=1}^{A}d^{\sum_{T=1,d|T}^{A}\mu(\frac{T}{d})\frac{A}{T}\frac{B}{T}\sum_{k=1}^{C}\gcd(d,k)}\\ =\prod_{d=1}^{A}d^{\sum_{T=1,d|T}^{A}\mu(\frac{T}{d})\frac{A}{T}\frac{B}{T}\sum_{x|d}\varphi(x)\frac{C}{x}}\\ =\prod_{T=1}^{A}(\prod_{d=1,d|T}^{A}d^{\mu(\frac{T}{d})\sum_{x|d}\varphi(x)\frac{C}{x}})^{\frac{A}{T}\frac{B}{T}}\\ =\prod_{T=1}^{A}(\prod_{d|T}\prod_{x|d}d^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}})^{\frac{A}{T}\frac{B}{T}}\\ =\prod_{T=1}^{A}(\prod_{d|T}\prod_{x|d}d^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}})^{\frac{A}{T}\frac{B}{T}}\\ \]

\(x|d|T\) 连着整除好奇怪。。。

考虑到 \(d=x\cdot \dfrac{d}{x}\) ,分成 \(2\) 部分算

部分一

\[\prod_{T=1}^{A}\prod_{d|T}\prod_{x|d}(\dfrac{d}{x})^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}\frac{A}{T}\frac{B}{T}}\\ =\prod_{x=1}^{A}\prod_{T=1}^{\frac{A}{x}}\prod_{x|d,d|Tx}(\dfrac{d}{x})^{\mu(\frac{Tx}{d})\varphi(x)\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}}\\ =\prod_{x=1}^{A}\prod_{T=1}^{\frac{A}{x}}\prod_{d|T}d^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}}\\ =\prod_{x=1}^{A}(\prod_{T=1}^{\frac{A}{x}}(\prod_{d|T}d^{\mu(\frac{T}{d})})^{\frac{A}{Tx}\frac{B}{Tx}})^{\varphi(x)\frac{C}{x}}\\ \]

\(O(n\log n)\) 预处理 \(d^{\mu(\frac{T}{d})}\) 外边两层整除分块即可 \(O(n)\)

小优化:\(\mu(x)\) 非零的个数并不多,实测 \(10000\) 不到一点,虽然有个 \(\log\) ,合起来近似 \(O(n)\) ,判一下 \(\mu\) 的值可以快一点。

部分二

\[ \prod_{T=1}^{A}\prod_{d|T}\prod_{x|d}x^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}\frac{A}{T}\frac{B}{T}}\\ =\prod_{x=1}^{A}\prod_{T=1}^{\frac{A}{x}}\prod_{x|d,d|Tx}x^{\mu(\frac{Tx}{d})\varphi(x)\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}}\\ =\prod_{x=1}^{A}\prod_{T=1}^{\frac{A}{x}}\prod_{d|T}x^{\mu(\frac{T}{d})\varphi(x)\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}}\\ =\prod_{x=1}^{A}x^{\sum_{T=1}^{\frac{A}{x}}\sum_{d|T}\mu(\frac{T}{d})\varphi(x)\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}}\\ =\prod_{x=1}^{A}x^{\varphi(x)\sum_{T=1}^{\frac{A}{x}}\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}\sum_{d|T}\mu(\frac{T}{d})}\\ \]

\(\sum_{d|T}\mu(\dfrac{T}{d})=\mu*I=\epsilon\)

所以只用计算 \(T=1\) 时的情形即可

\[ =\prod_{x=1}^{A}x^{\varphi(x)\sum_{T=1}^{\frac{A}{x}}\frac{C}{x}\frac{A}{Tx}\frac{B}{Tx}\sum_{d|T}\mu(\frac{T}{d})}\\ =\sum_{x=1}^{A}x^{\varphi(x)\frac{C}{x}\frac{A}{x}\frac{B}{x}} \]

整除分块就够了!

注意事项

  • 指数取模要模 \(mod-1\)

  • long long 别少开,1ll 别少乘

  • 整除分块内层要快速幂的时候预处理逆元,否则单次询问变成 \(O(n\log n)\)

心力憔悴啊,毒瘤。

提供一组大样例以供调试

Input
3 998244353
6 6 6
100000 100000 100000
99998 99999 100000
Output
570465346 682784945 524427235
862376103 371412326 358248208
103815203 127873959 745848036
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
#define pb(x) push_back(x)
#define mkp(x,y) make_pair(x,y)
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
	return x*f;
}
const int N=100005;
int T,mod,A,B,C,iv6;
int mu[N],pri[N/9],cnt,jc[N],jp[N],sm[N],jk[N],st[N],phi[N],fp[N],vf[N];
bool vis[N];
int qpow(int n,int k,int res=1){
	for(;k;k>>=1,n=1ll*n*n%mod)
		if(k&1)res=1ll*n*res%mod;
	return res;
}
void Sieve(const int N=100000){
	mu[1]=1,phi[1]=1,jc[0]=1,jp[0]=1,jk[0]=1,st[0]=1,fp[0]=1,fp[1]=1,vf[0]=1;
	for(int i=2;i<=N;++i){
		fp[i]=1;
		if(!vis[i])pri[++cnt]=i,mu[i]=-1,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*pri[j]<=N;++j){
			vis[i*pri[j]]=1;
			if(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]];
		}
	}
	for(int i=1;i<=N;++i){
		if(!mu[i])continue;
		for(int j=1;i*j<=N;++j)
			if(mu[i]==1)fp[i*j]=1ll*fp[i*j]*j%mod;
			else fp[i*j]=1ll*fp[i*j]*qpow(j,mod-2)%mod;
	}
	for(int i=1;i<=N;++i)fp[i]=1ll*fp[i]*fp[i-1]%mod,vf[i]=qpow(fp[i],mod-2);
	for(int i=1;i<=N;++i)
		jc[i]=1ll*jc[i-1]*i%mod,
		jp[i]=1ll*jp[i-1]*qpow(i,i)%mod,
		sm[i]=(sm[i-1]+1ll*mu[i]*i%(mod-1)*i%(mod-1))%(mod-1),
		jk[i]=1ll*jk[i-1]*qpow(i,1ll*i*i%(mod-1))%mod,
		mu[i]+=mu[i-1],
		st[i]=1ll*st[i-1]*qpow(i,phi[i])%mod,
		phi[i]=(phi[i]+phi[i-1])%(mod-1);
/*
	Attention:
	mu:∑μ
	jc :阶乘 mod mod
	jp : i^i 的前缀积 mod mod
	sm:∑μ(x)*x*x mod (mod-1)
	jk:∏i^(i^2) mod (mod-1)
	phi:∑φ mod (mod-1)
	st:πT^phi(T) mod mod
	fp:∑π(d|T)d^μ(T/d) mod mod
	vf:qpow(fp,mod-2)
*/
}
namespace Task0{
	int fz,fm;
	int f(int n,int m){
		if(n>m)n^=m^=n^=m;
		int res=0;
		for(int l=1,r;l<=n;l=r+1)
			r=min(n/(n/l),m/(m/l)),res=(res+1ll*(n/l)*(m/l)%(mod-1)*(mu[r]-mu[l-1])%(mod-1))%(mod-1);
		return (res+mod-1)%(mod-1);
	}
	int g(int n,int m){
		if(n>m)n^=m^=n^=m;
		int res=1;
		for(int l=1,r;l<=n;l=r+1)
			r=min(n/(n/l),m/(m/l)),res=1ll*res*qpow(1ll*jc[r]*qpow(jc[l-1],mod-2)%mod,f(n/l,m/l))%mod;
		return (res+mod)%mod;
	}
	void main(){
		fz=qpow(1ll*qpow(jc[A],B)*qpow(jc[B],A)%mod,C)%mod;
		fm=qpow(1ll*qpow(g(A,B),C)*qpow(g(A,C),B)%mod,mod-2);
		printf("%lld ",1ll*fz*fm%mod);
	}
}
namespace Task1{
	int fz,fm;
	int s(int x,int y){
		return (1ll*x*(x+1)/2%(mod-1))*(1ll*y*(y+1)/2%(mod-1))%(mod-1);
	}
	int s2(int x){
		return 1ll*x*(x+1)%mod*(x+x+1)%mod*iv6%mod;
	}
	int f(int n,int m){
		if(n>m)n^=m^=n^=m;
		int res=0;
		for(int l=1,r;l<=n;l=r+1){
			r=min(n/(n/l),m/(m/l));
			res=(res+1ll*s(n/l,m/l)*(sm[r]-sm[l-1])%(mod-1))%(mod-1);
		}
		return (res+mod-1)%(mod-1);
	}
	int g(int n,int m){
		if(n>m)n^=m^=n^=m;
		int res=1;
		for(int l=1,r;l<=n;l=r+1){
			r=min(n/(n/l),m/(m/l));
			res=1ll*res*qpow(1ll*jk[r]*qpow(jk[l-1],mod-2)%mod,f(n/l,m/l))%mod;
		}
		return (res+mod)%mod;
	}
	void main(){
		fz=qpow(1ll*qpow(jp[A],1ll*B*(B+1)/2%(mod-1))*qpow(jp[B],1ll*A*(A+1)/2%(mod-1))%mod,1ll*C*(C+1)/2%(mod-1));
		fm=qpow(1ll*qpow(g(A,B),1ll*C*(C+1)/2%(mod-1))*qpow(g(A,C),1ll*B*(B+1)/2%(mod-1))%mod,mod-2);
		printf("%lld ",1ll*fz*fm%mod);
	}
}
namespace Task2{
	int fz,fm;
	int f(int A,int B,int C){
		int res=1;
		for(int l=1,r,mx=min(A,min(B,C));l<=mx;l=r+1){
			r=min(A/(A/l),min(B/(B/l),C/(C/l)));
			res=1ll*res*qpow(jc[A/l],1ll*(B/l)*(C/l)%(mod-1)*(phi[r]-phi[l-1]+mod-1)%(mod-1))%mod;
			res=1ll*res*qpow(1ll*st[r]*qpow(st[l-1],mod-2)%mod,1ll*(A/l)*(B/l)*(C/l)%(mod-1))%mod;
		}
		return res;
	}
	int h(int n,int m){
		if(n>m)n^=m^=n^=m;
		int res=1;
		for(int l=1,r;l<=n;l=r+1){
			r=min(n/(n/l),m/(m/l));
			res=1ll*res*qpow(1ll*fp[r]*vf[l-1]%mod,1ll*(n/l)*(m/l)%(mod-1))%mod;
		}
		return res;
	}
	int g(int A,int B,int C){
		int res=1;
		for(int l=1,r,mx=min(A,min(B,C));l<=mx;l=r+1){
			r=min(A/(A/l),min(B/(B/l),C/(C/l)));
			res=1ll*res*qpow(1ll*st[r]*qpow(st[l-1],mod-2)%mod,1ll*(A/l)*(B/l)*(C/l)%(mod-1))%mod;
			res=1ll*res*qpow(h(A/l,B/l),1ll*(phi[r]-phi[l-1]+mod-1)*(C/l)%(mod-1))%mod;
		}
		return res;
	} 
	void main(){
		fz=1ll*f(A,B,C)*f(B,A,C)%mod;
		fm=qpow(1ll*g(A,B,C)*g(A,C,B)%mod,mod-2);
		printf("%lld ",1ll*fz*fm%mod);
	}
}

signed main(){
	T=read(),mod=read(),iv6=qpow(6,mod-2),Sieve();
	while(T--) {
		A=read(),B=read(),C=read();
		Task0::main(),Task1::main(),Task2::main(),puts("");
	}
}
posted @ 2020-10-02 11:12  zzctommy  阅读(166)  评论(0编辑  收藏  举报