luogu P4619 [SDOI2018]旧试题

luogu

先考虑\(d(i,j,k)\)是啥,首先会有\(d(i,j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\),可以推广得到\(d(i,j,k)=\sum_{x|i}\sum_{y|j}\sum_{z|k}[gcd(x,y)=1][gcd(y,z)=1][gcd(x,z)=1]\),然后开始化式子

\(\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\sum_{x|i}\sum_{y|j}\sum_{z|k}[gcd(x,y)=1][gcd(y,z)=1][gcd(x,z)=1]\)

\(\sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\sum_{x|i}\sum_{y|j}\sum_{z|k}\sum_{a|x,a|y}\mu(a)\sum_{b|y,b|z}\mu(b)\sum_{c|z,c|x}\mu(c)\)

\(\sum_{a=1}^{\min(A,B)}\sum_{b=1}^{\min(B,C)}\sum_{c=1}^{\min(C,A)}\mu(a)\mu(b)\mu(c)\sum_{\mathrm{lcm}(c,a)|x}\sum_{\mathrm{lcm}(a,b)|y}\sum_{\mathrm{lcm}(b,c)|z}\lfloor\frac{A}{x}\rfloor\lfloor\frac{B}{y}\rfloor\lfloor\frac{C}{z}\rfloor\)

这里记\(F_A(x)=\sum_{x|i}\lfloor\frac{A}{i}\rfloor\),\(F_B(x),F_C(x)\)同理,可得

\(\sum_{a=1}^{\min(A,B)}\sum_{b=1}^{\min(B,C)}\sum_{c=1}^{\min(C,A)}\mu(a)\mu(b)\mu(c)F_A(\mathrm{lcm}(c,a))F_B(\mathrm{lcm}(a,b))F_C(\mathrm{lcm}(b,c))\)

到这个时候就可以讨论了,首先是\(a=b=c\)的情况,可以做到\(O(n)\)统计;然后是\(abc\)中两个相等且另外一个不相等,以及三个都不相等的情况.答案的这个形式就是枚举三个不同的数,然后考虑他们两两之间的贡献,可以联想到建图,连上所有的\((a,b,\mathrm{lcm}(a,b))\)即可套三元环计数.然后我们显然只用考虑\(\mu(a)\neq 0,\mu(b)\neq 0,\mathrm{lcm}(a,b)\le \max\{A,B,C\}\)的边,可以发现这样的边只有约\(8*10^5\)条,所以如果是\(abc\)中两个相等且和另外一个不相等的情况,就是一次枚举每条边,然后枚举这条边会对应的\(aab,abb,aac,acc,bbc,bcc\)六种情况;如果是\(abc\)都不相等,那么对应到图上就是枚举一个三元环,所以使用三元环计数即可,枚举三元环复杂度\(O(|E|^{1.5})\),再讨论这三个点分别\(abc\)中的哪个来统计答案

然后这题较卡常,首先\(F_A,F_B,F_C\)可以\(O(nlogn)\)预处理;然后是建图问题,因为\(\mathrm{lcm}(a,b)=\gcd(a,b)\frac{a}{\gcd(a,b)}\frac{b}{\gcd(a,b)}\),那么只要枚举\(\gcd(a,b)\frac{a}{\gcd(a,b)}\frac{b}{\gcd(a,b)}\)并且保证他们的乘积\(\le \max\{A,B,C\}\),可以发现这个复杂度类似调和极数,为\(O(nlog^2n)\);还有就是能并在一起计算的式子最好并在一起

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long

using namespace std;
const int N=1e5+10,M=N*10,mod=1e9+7;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    return x*w;
}
/*int to[M],nt[M],w[M],hd[N],tot=1;
void adde(int x,int y,int z){++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;}*/
void ad(int &x,int y){x+=y,x-=x>=mod?mod:0;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int prm[N],pp[N],f[N],g[N],h[N],mu[N],tt,nm[N],tn,id[N],dg[N],vs[N],te;
int n,a,b,c,ans;
void inii(int *f,int nn)
{
    memset(f,0,sizeof(int)*(n+1));
    for(int i=1;i<=nn;++i)
	for(int j=1;i*j<=nn;++j)
	    ad(f[i],nn/(i*j));
}
struct node{int x,y,z;}ee[M];
vector<node> gg[N];
vector<node>::iterator i1,i2;

int main()
{
///wdnmd
    mu[1]=1;
    for(int i=2;i<=N-5;++i)
    {
    	if(!pp[i]) pp[i]=1,prm[++tt]=i,mu[i]=-1;
    	for(int j=1;i*prm[j]<=N-5;++j)
    	{
    	    if(i%prm[j]==0){pp[i*prm[j]]=pp[i]+1;break;}
    	    pp[i*prm[j]]=1,mu[i*prm[j]]=-mu[i];
    	}
    }
    for(int i=1;i<=N-5;++i)
	if(mu[i]) nm[++tn]=i,id[i]=tn;
    int lt=tn,T=rd();
    while(T--)
    {
    	a=rd(),b=rd(),c=rd();
    	n=max(max(a,b),c);
    	inii(f,a),inii(g,b),inii(h,c);
    	tn=lt;
    	while(nm[tn]>n) --tn;
    	te=0;
    	memset(dg,0,sizeof(int)*(n+1))/*,memset(hd,0,sizeof(int)*(n+1)),tot=1*/;
    	for(int d=1;d<=n;++d)
    	    for(int i=1;1ll*i*d<=n;++i)
    	    	for(int j=i+1;1ll*i*j*d<=n;++j)
    	    	    if(mu[i*d]&&mu[j*d]&&gcd(i,j)==1) ++dg[id[i*d]],++dg[id[j*d]],ee[++te]=(node){id[i*d],id[j*d],i*j*d};
    	for(int i=1;i<=tn;++i) gg[i].clear();
    	for(int i=1;i<=te;++i)
    	{
    	    int x=ee[i].x,y=ee[i].y,z=ee[i].z;
    	    if(dg[x]>dg[y]) swap(x,y);
    	    gg[x].push_back((node){i,y,z});
    	}
    	ans=0;
    	for(int x=1;x<=tn;++x)
    	{
    	    for(i1=gg[x].begin();i1!=gg[x].end();++i1)
    	    {
        		int i=(*i1).x,y=(*i1).y,xx=nm[x],yy=nm[y],w=(*i1).z;
        		vs[y]=i;
        		int nw=(1ll*f[xx]*g[w]%mod*h[w]+1ll*f[w]*g[xx]%mod*h[w]+1ll*f[w]*g[w]%mod*h[xx])%mod;
        		ad(ans,(~(mu[xx]*mu[xx]*mu[yy])?nw:mod-nw));
        		nw=(1ll*f[yy]*g[w]%mod*h[w]+1ll*f[w]*g[yy]%mod*h[w]+1ll*f[w]*g[w]%mod*h[yy])%mod;
        		ad(ans,(~(mu[xx]*mu[yy]*mu[yy])?nw:mod-nw));
    	    }
    	    for(i1=gg[x].begin();i1!=gg[x].end();++i1)
    	    {
        		int i=(*i1).x,y=(*i1).y;
        		for(i2=gg[y].begin();i2!=gg[y].end();++i2)
        		{
        		    int j=(*i2).x,z=(*i2).y;
        		    if(vs[z])
        		    {
            			int k=vs[z],w1=ee[i].z,w2=ee[j].z,w3=ee[k].z;
            			int nw=(1ll*f[w1]*g[w2]%mod*h[w3]+1ll*f[w1]*g[w3]%mod*h[w2]+1ll*f[w2]*g[w1]%mod*h[w3]+1ll*f[w2]*g[w3]%mod*h[w1]+1ll*f[w3]*g[w1]%mod*h[w2]+1ll*f[w3]*g[w2]%mod*h[w1])%mod;
            			ad(ans,(~(mu[nm[x]]*mu[nm[y]]*mu[nm[z]])?nw:mod-nw));
        		    }
        		}
            }
        	for(i1=gg[x].begin();i1!=gg[x].end();++i1) vs[(*i1).y]=0;
    	}
    	for(int i=1;i<=tn;++i)
    	{
    	    int nw=1ll*f[nm[i]]*g[nm[i]]%mod*h[nm[i]]%mod;
    	    ad(ans,(~(mu[nm[i]]*mu[nm[i]]*mu[nm[i]])?nw:mod-nw));
    	}
    	printf("%d\n",ans);
    }
    return 0;
}
posted @ 2020-03-03 11:23  ✡smy✡  阅读(102)  评论(0编辑  收藏  举报