P5518-[MtOI2019]幽灵乐团【莫比乌斯反演,欧拉反演】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P5518


1|1题目大意

T次给出A,B,C求以下三个式子

i=1Aj=1Bk=1Clcm(i,j)gcd(i,k)

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))i×j×k

i=1Aj=1Bk=1C(lcm(i,j)gcd(i,k))gcd(i,j,k)

1T70,1A,B,C105


1|2解题思路

开始写了个O(Tnlogn)结果发现不能过,然后就多浪费了三个多小时
在这里插入图片描述
只需要用到两个反演的式子

F(i)=i|df(d)f(i)=i|dμ(di)F(d)

gcd(S)=xS,d|xφ(d)

然后因为推导过程出来冗长以外没有太多难的部分,所以推荐自己手推到不会的再翻题解。

然后就开始吧,因为lcm(i,j)=ijgcd(i,j)所以问题可以化为两个部分,求

(i=1Aj=1Bk=1Cij)f(type),(i=1Aj=1Bk=1C1gcd(i,j))f(type)

首先是第一个式子f(type)=1
第一部分就是

i=1AiB×C×j=1BjA×C

这个十分简单,我们预处理阶乘就可以做到O(logP)
然后第二部分考虑枚举约数

d=11dC×i=1Aj=1B[gcd(i,j)=d]

然后莫反

d=11dCk=1μ(k)AkdBkd

显然的我们可以d,k都可以整除分块,预处理一下逆元的前缀乘积就可以快速计算区间逆元乘积了。

第一个式子时间复杂度O(n34)

然后第二个式子类似的,记S(n)=n×(n+1)2那么有

i=1AiiS(B)S(C)×j=1BjjS(A)(C)

维护一个ii的前缀积即可。
第二部分

d=11dS(C)×i=1Aj=1Bij[gcd(i,j)=d]d=11dS(C)k=1μ(k)S(Akd)S(Bkd)

需要提前处理μ(i)×i2的前缀和,i2,1i2的前缀积就好了

第二个式子时间复杂度O(n34)

主要的难点在第三个式子
首先第一部分先只考虑i

i=1Aj=1Bk=1Cigcd(i,j)

考虑欧拉反演,枚举约数

d=1(iAdi×d)φ(d)BdCd

fi=j=1ii那么有

d=1(fAddAd)φ(d)BdCd

拆开来fd的部分

d=1(fAd)φ(d)BdCd×dφ(d)AdBdCd

预处理出f数组,和g数组gi=j=1ijφ(j)φ的前缀和就可以整除分块搞了

然后是第二部分

i=1Aj=1Bk=1C1gcd(i,j)gcd(i,j,k)

你可以试一下枚举gcd(i,j),反正我推了好久都没有对出来/kk
所以考虑枚举gcd(i,j,k)的约数然后欧拉反演里面再莫反

d=1(k=11dkz=1μ(z)AdkzBdkz)φ(d)Cd

然后把1d1k分开处理

d=1(k=11kz=1μ(z)AdkzBdkz)φ(d)Cd

×d=1(1d)φ(d)Cdk=1z=1μ(z)AdkzBdkz

(至于为什么要这么分开,会注意到第一个式子如果我们进行两次整除分块,那么对于每个1dk就会有两个影响它的指数φ(d)z=1μ(z)AdkzBdkz所以很难处理,此时我们分开来就可以直接用区间的值来做了)

注意到这样要做三次整除分块,十分地慢,但是考虑后面那个式子z=1μ(z)AdkzBdkz对于一个固定的dk是一个确定的值的,并且因为是整除分块,所以不同的值不多我们可以考虑预处理这个东西,整除分块一个dk然后里面再整除分块计算就好了。

还有拆开后处理1d的式子需要预处理1dφ(d)的前缀积。

然后就做完了,第三部分时间复杂度O(n+n34logn)

实际上其实最后的式子两个部分可以约掉一些东西省一些常数,但是这样做也能过但是得开int。

或者你可以用别的方法卡卡常反正我开int了。


1|3code

因为中途long long改int所以代码巨丑

#include<cstdio> #include<cstring> #include<algorithm> //#define int long long using namespace std; const int N=1e5+10; int T,P,Phi,A,B,C,ans,cnt;bool v[N]; int pri[N/10],mu[N],su[N],phi[N],f[N],g[N],h[N]; int inv[N],inc[N],inw[N],fac[N],gac[N],hac[N]; int power(int x,int b){ int ans=1;b=(b%Phi+Phi)%Phi; while(b){ if(b&1)ans=ans*1ll*x%P; x=x*1ll*x%P;b>>=1; } return ans; } int Sum(int n) {return n*1ll*(n+1)/2%Phi;} int Tum(int n) {return n*1ll*(n+1)*1ll*(2ll*1ll*n+1)/6ll%Phi;} void Prime(){ mu[1]=phi[1]=1; for(int i=2;i<N;i++){ if(!v[i])pri[++cnt]=i,mu[i]=-1,phi[i]=i-1; for(int j=1;j<=cnt&&i*1ll*pri[j]<N;j++){ v[i*1ll*pri[j]]=1; if(i%pri[j]==0){ phi[i*1ll*pri[j]]=phi[i]*1ll*pri[j]; break; } mu[i*1ll*pri[j]]=-mu[i]; phi[i*1ll*pri[j]]=phi[i]*1ll*(pri[j]-1); } } inc[1]=fac[0]=gac[0]=inw[0]=inv[0]=hac[0]=1; for(int i=2;i<N;i++)inc[i]=P-inc[P%i]*1ll*(P/i)%P; for(int i=1;i<N;i++)fac[i]=fac[i-1]*1ll*i%P; for(int i=1;i<N;i++)gac[i]=gac[i-1]*1ll*power(i,i)%P; for(int i=1;i<N;i++)hac[i]=hac[i-1]*1ll*power(i,i*1ll*i%Phi)%P; for(int i=1;i<N;i++)inw[i]=inw[i-1]*1ll*power(inc[i],i*1ll*i%Phi)%P; for(int i=1;i<N;i++)inv[i]=inv[i-1]*1ll*inc[i]%P; for(int i=1;i<N;i++)su[i]=su[i-1]+mu[i]; g[0]=h[0]=1; for(int i=1;i<N;i++)g[i]=g[i-1]*1ll*power(inc[i],phi[i])%P; for(int i=1;i<N;i++)h[i]=h[i-1]*1ll*power(i,phi[i])%P; for(int i=1;i<N;i++)(phi[i]+=phi[i-1])%=Phi; return; } void qart1(int A,int B,int C){ int n=min(A,B); for(int L=1,R;L<=n;L=R+1){ R=min(A/(A/L),B/(B/L)); int a=A/L,b=B/L,m=min(a,b),w=0; for(int l=1,r;l<=m;l=r+1){ r=min(a/(a/l),b/(b/l)); (w+=(su[r]-su[l-1])*(a/l)*1ll*(b/l)%Phi)%=Phi; } ans=ans*1ll*power(inv[R]*1ll*fac[L-1]%P,w*1ll*C%Phi)%P; } return; } void part1(){ ans=power(fac[A],B*1ll*C%Phi)*1ll*power(fac[B],A*1ll*C%Phi)%P; qart1(A,B,C);qart1(A,C,B); printf("%d ",ans);return; } void qart2(int A,int B,int C){ int n=min(A,B); for(int i=1;i<=n;i++)f[i]=(f[i-1]+mu[i]*1ll*i*1ll*i%Phi)%Phi; for(int L=1,R;L<=n;L=R+1){ R=min(A/(A/L),B/(B/L)); int a=A/L,b=B/L,m=min(a,b),w=0; for(int l=1,r;l<=m;l=r+1){ r=min(a/(a/l),b/(b/l)); (w+=Sum(a/l)*1ll*Sum(b/l)%Phi*1ll*(f[r]-f[l-1])%Phi)%=Phi; } w=w*1ll*Sum(C)%Phi; ans=ans*1ll*power(inw[R]*1ll*hac[L-1]%P,w)%P; } return; } void part2(){ ans=power(gac[A],Sum(B)*1ll*Sum(C)%Phi)*1ll*power(gac[B],Sum(A)*1ll*Sum(C)%Phi)%P; qart2(A,B,C);qart2(A,C,B); printf("%d ",ans);return; } void qart3(int A,int B,int C){ int n=min(A,B); for(int L=1,R;L<=n;L=R+1){ R=min(A/(A/L),B/(B/L)); int a=A/L,b=B/L,m=min(a,b),w=0; for(int l=1,r;l<=m;l=r+1){ r=min(a/(a/l),b/(b/l)); (w+=1ll*(a/l)*(b/l)*(su[r]-su[l-1])%Phi)%=Phi; } for(int i=L;i<=R;i++)f[i]=w; } n=min(n,C); for(int L=1,R;L<=n;L=R+1){ R=min(A/(A/L),min(B/(B/L),C/(C/L))); int a=A/L,b=B/L,c=C/L,m=min(a,b),w=0,s=1; for(int l=1,r;l<=m;l=r+1){ r=min(a/(a/l),b/(b/l)); (w+=1ll*f[l*1ll*L]*(r-l+1)%Phi)%=Phi; s=1ll*s*power(1ll*inv[r]*fac[l-1]%P,f[l*1ll*L])%P; } ans=ans*1ll*power(1ll*g[R]*power(g[L-1],P-2)%P,1ll*w*(C/L)%Phi)%P; ans=ans*1ll*power(s,1ll*(phi[R]-phi[L-1])*(C/L)%Phi)%P; } // for(int i=1;i<=A;i++) // for(int j=1;j<=B;j++) // for(int k=1;k<=C;k++) // ans=ans*1ll*power(inc[__gcd(i,j)],__gcd(__gcd(i,j),k))%P; return; } void part3(){ ans=1; int n=min(A,min(B,C)); for(int L=1,R;L<=n;L=R+1){ R=min(A/(A/L),min(B/(B/L),C/(C/L))); int a=A/L,b=B/L,c=C/L; // b=fac[b]*1ll*power(Sum(R)-Sum(L-1),b)%P; ans=1ll*ans*power(fac[a],1ll*(phi[R]-phi[L-1])*b*c%Phi)%P; ans=1ll*ans*power(fac[b],1ll*(phi[R]-phi[L-1])*a*c%Phi)%P; ans=1ll*ans*power(h[R]*1ll*power(h[L-1],P-2)%P,2ll*a*b*c%Phi)%P; } // int k=ans; qart3(A,B,C);qart3(A,C,B); // else ans=1ll*ans*ans%P*power(k,P-2)%P; printf("%d ",ans);return; } signed main() { scanf("%d%d",&T,&P); Phi=P-1;Prime(); while(T--){ scanf("%d%d%d",&A,&B,&C); // A=B=C=1e5; part1(); part2(); part3(); putchar('\n'); } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15594319.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(80)  评论(2编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示