Processing math: 100%

[SDOI2018]旧试题

题目大意

给定A,B,C,求:

Ai=1Bj=1Ck=1d(ijk)   mod 109+7

题解

σ0(ijk)=x|iy|jz|k[(x,y)==1][(x,z)==1][(y,z)==1]

那么我们的答案就是:

ai=1bj=1ck=1x|iy|jz|k[(x,y)==1][(x,z)==1][(y,z)==1]

ax=1by=1cz=1axbycz[(x,y)==1][(x,z)==1][(y,z)==1]

ax=1by=1cz=1axbyczu|(x,y)μ(u)v|(x,z)μ(v)w|(y,z)μ(w)

min(x,y)u=1min(x,z)v=1min(y,z)w=1μ(u)μ(v)μ(w)[u,v]|xax[u,w]|yby[v,w]|zcz

后面的东西我们可以预处理出来,现在我们需要考虑的是计算有序三元组(u,v,w)产生的贡献。

通过打表找规律可以发现有用的边非常少,所以就可以三元环计数了。

然后我们还需要降低连边的复杂度。

我们先枚举三个元素相同的的情况。

通过看题解我们有一种枚举方式,枚举两个数的gcd,再去枚举两个数,并且要保证μ(x)!=0&&μ(y)!=0&&(x/g,y/g)==1

然后这样我们可以处理有两个元素相同的情况。

三元环计数

参考:https://www.luogu.org/blog/KingSann/fou-chang-yong-di-hei-ke-ji-san-yuan-huan-post

首先我们要给无向图定向,我们先强制规定一下顺序,就是度数小的向度数大的连边,如果一样,就按照编号大小连边。

这样一定会连出一个DAG

然后统计答案的方法就是枚举点u,将u的所有出边都标记一下。

再去枚举u的出点的出点,如果这个出点是u那么这就是一个三元环。

这样可以保证每个三元环只会被统计一次。

再去考虑复杂度。

mi=1out[toi]

考虑这个东西的级别。

out[toi]m时,因为一共只有m条边,这样的点本身只有m个,所以复杂度上界是mm

out[toi]<m时,最多会有n个点连向它,所以复杂度上界是nm的 。

然后就做完了。

这题还有一个trick,就是只需要在最后取模。

代码

#include<bits/stdc++.h>
#define N 100009
using namespace std;
typedef long long ll;
const int maxn=100000;
const int mod=1e9+7;
int mu[N],prime[N],T,du[N];
ll fa[N],fb[N],fc[N],a,b,c,ans,val[N],tag[N];
bool vis[N];
inline ll rd(){
	ll x=0;char c=getchar();bool f=0;
	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f?-x:x;
}
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline void MOD(int &x){x=x>=mod?x-mod:x;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline void prework(){
	mu[1]=1;
	int k;
	for(int i=2;i<=maxn;++i){
		if(!vis[i]){prime[++prime[0]]=i;mu[i]=-1;}
		for(int j=1;j<=prime[0]&&(k=i*prime[j])<=maxn;++j){
			vis[k]=1;
			if(i%prime[j]==0){mu[k]=0;break;}
			mu[k]=-mu[i];
		}
	}
}
struct edge{int u,v;ll val;};
vector<edge>vec;
vector<edge>::iterator it;
struct node{int to;ll val;};
vector<node>ed[N];
vector<node>::iterator it2,it3;
int main(){
	prework();
	T=rd();
	while(T--){
		a=rd();b=rd();c=rd();
		vec.clear();
		int mx=max(max(a,b),c);
		int mi=min(min(a,b),c);
		memset(fa,0,sizeof(fa));
		memset(fb,0,sizeof(fb));
		memset(fc,0,sizeof(fc));
		memset(du,0,sizeof(du));
		ans=0;
		for(int i=1;i<=a;++i)
		  for(int j=i;j<=a;j+=i)fa[i]+=a/j;
		for(int i=1;i<=b;++i)
		  for(int j=i;j<=b;j+=i)fb[i]+=b/j;
		for(int i=1;i<=c;++i)
		  for(int j=i;j<=c;j+=i)fc[i]+=c/j;
		for(int i=1;i<=mi;++i)if(mu[i]){
			ans+=mu[i]*mu[i]*mu[i]*fa[i]*fb[i]*fc[i];
		}
		for(int g=1;g<=mx;++g)
		  for(int i=1;i*g<=mx;++i)if(mu[i*g])
		    for(int j=i+1;1ll*i*j*g<=mx;++j)if(mu[j*g]&&gcd(i,j)==1){
		    	int x=i*g,y=j*g;ll z=i*g*j;
		    	int xx=mu[x]*mu[x]*mu[y],yy=mu[x]*mu[y]*mu[y];
		    	ans+=xx*(fa[x]*fb[z]*fc[z]+fa[z]*fb[x]*fc[z]+fa[z]*fb[z]*fc[x]);
		    	ans+=yy*(fa[y]*fb[z]*fc[z]+fa[z]*fb[y]*fc[z]+fa[z]*fb[z]*fc[y]);
		    	du[x]++;du[y]++;
		    	vec.push_back(edge{x,y,z});
			}
		for(it=vec.begin();it!=vec.end();++it){
			edge x=*it;
			if(du[x.u]<du[x.v])swap(x.u,x.v);
			else if(du[x.u]==du[x.v]&&x.u>x.v)swap(x.u,x.v);
			ed[x.u].push_back(node{x.v,x.val}); 
		}
		for(int i=1;i<=mx;++i){
			for(it2=ed[i].begin();it2!=ed[i].end();++it2){
				node x=*it2;
				tag[x.to]=i;
				val[x.to]=x.val;
			}
			for(it2=ed[i].begin();it2!=ed[i].end();++it2){
				node x=*it2;
				for(it3=ed[x.to].begin();it3!=ed[x.to].end();++it3){
					node y=*it3;
					if(tag[y.to]!=i)continue;
					ll xx=val[y.to],yy=x.val,zz=y.val,tg=mu[i]*mu[x.to]*mu[y.to];
					ans+=tg*(fa[xx]*fb[yy]*fc[zz]+
					         fa[yy]*fb[zz]*fc[xx]+
					         fa[xx]*fb[zz]*fc[yy]+
					         fa[yy]*fb[xx]*fc[zz]+
					         fa[zz]*fb[xx]*fc[yy]+
					         fa[zz]*fb[yy]*fc[xx]);
				}
			}	
		}
		for(int i=1;i<=mx;++i)ed[i].clear();
		printf("%lld\n",ans%mod);
	}
	return 0;
}

这样我们枚举的复杂度就是mm

posted @   comld  阅读(244)  评论(0编辑  收藏  举报
编辑推荐:
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
阅读排行:
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· 程序员转型AI:行业分析
· 为DeepSeek添加本地知识库
· 深入集成:使用 DeepSeek SDK for .NET 实现自然语言处理功能
· .NET程序员AI开发基座:Microsoft.Extensions.AI
点击右上角即可分享
微信分享提示