zoukankan      html  css  js  c++  java
  • 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 imes j}{gcd(i,j) imes 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} imes(B!)^{A})^C ]

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

      type=1

      [prod_{i=1}^{A}prod_{j=1}^{B}prod_{k=1}^{C}(dfrac{i imes j}{gcd(i,j) imes 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 imes(B+1)/2} imes (jp_B)^{A imes(A+1)/2})^{C imes(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 imes(C+1)/2}\ =(prod_{d=1}^{A}d^{f(A,B,d)})^{C imes(C+1)/2}\ ]

      其中

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

      带回原式换个写法

    [ =(prod_{d=1}^{A}d^{f(A,B,d)})^{C imes(C+1)/2}\=(prod_{d=1}^{A}d^{g(frac{A}{d},frac{B}{d})*d^2})^{C imes(C+1)/2}\=(prod_{d=1}^{A}(d^{(d^2)})^{g(frac{A}{d},frac{B}{d})})^{C imes(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 imes j}{gcd(i,j) imes 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)dfrac{B}{dx}frac{C}{dx}}\ =prod_{T=1}^{A}prod_{d|T}^{}prod_{i=1}^{frac{A}{T}}(iT)^{mu(frac{T}{d})dfrac{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})dfrac{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)}) 的前缀积和 (sumvarphi(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}xsum_{k=1}^{frac{C}{x}}[gcd(dfrac{d}{x},k)==1]\ =sum_{x|d}xsum_{k=1}^{frac{C}{x}}sum_{t|gcd(frac{d}{x},k)}mu(t)\ =sum_{x|d}xsum_{t=1}^{frac{C}{x}}mu(t)dfrac{C}{tx}\ =sum_{x|d}xsum_{T=1,x|T}^{C}mu(dfrac{T}{x})dfrac{C}{T}\ =sum_{T=1,T|d}^{C}dfrac{C}{T}sum_{x|T}xmu(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=xcdot 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(nlog 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(nlog 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("");
    	}
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    python 函数嵌套
    python 函数对象
    python 函数参数
    python 连接MySQL报错及解决方案
    解决 No module named pip
    python 文件处理
    python
    python 元祖
    python 读取域名信息
    ubuntu 配置网卡,DNS, iptables
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13752763.html
Copyright © 2011-2022 走看看