[CF809E] Surprise me!

\(\text{Problem}:\)Surprise me!

\(\text{Solution}:\)

发现 \(\varphi\) 内有两数相乘,将其展开,有:

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{\varphi(a_{i})\varphi(a_{j})\gcd(a_{i},a_{j})}{\varphi(\gcd(a_{i},a_{j}))}dist(i,j) \]

套路的,先枚举 \(\gcd\),有:

\[\sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(a_{i},a_{j})=d]\varphi(a_{i})\varphi(a_{j})dist(i,j)=\sum\limits_{d=1}^{n}\frac{d}{\varphi(d)}f(d) \]

现在转化 \([\gcd(a_{i},a_{j})=d]\)。考虑只枚举被 \(d\) 整除的 \(a_{i}\),有:

\[\begin{aligned} f(d)&=\sum\limits_{i=1}^{m_{d}}\sum\limits_{j=1}^{m_{d}}[\gcd(\frac{a_{p_{i}}}{d},\frac{a_{p_{j}}}{d})=1]\varphi(a_{p_{i}})\varphi(a_{p_{j}})dist(p_{i},p_{j})\\ &=\sum\limits_{i=1}^{m_{d}}\sum\limits_{j=1}^{m_{d}}\varphi(a_{p_{i}})\varphi(a_{p_{j}})dist(p_{i},p_{j})\sum\limits_{kd\mid \gcd(a_{p_{i}},a_{p_{j}})}\mu(k)\\ &=\sum\limits_{k=1}^{\lfloor\frac{n}{d}\rfloor}\mu(k)\sum\limits_{i=1}^{m_{dk}}\sum\limits_{j=1}^{m_{dk}}\varphi(a_{p_{i}})\varphi(a_{p_{j}})dist(p_{i},p_{j}) \end{aligned} \]

发现 \(a_{i}\) 互不相同。由于 \(\sum\limits_{i=1}^{m}m_{i}\),即因数个数的前缀和,是 \(O(n\log n)\) 级别的,故考虑对于每个 \(k\),求出:

\[g(k)=\sum\limits_{i=1}^{m_{k}}\varphi(a_{p_{i}})\sum\limits_{j=1}^{m_{k}}\varphi(a_{p_{j}})dist(p_{i},p_{j}) \]

由于关键点个数很少,建出虚树,在虚树上做换根 \(dp\) 即可求得答案。

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=200010, M=19, Mod=1e9+7;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,a[N],ans; vector<int> q[N];
int st[N<<1][M],tot,id[N],dep[N],lg[N<<1],pri[N/10],cnt,book[N],phi[N],mu[N];
int sta[N],tp,g[N],res,now,F[N];
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%Mod) if(p&1) res=1ll*res*x%Mod; return res; }
int head[N],maxE; struct Edge { int nxt,to,rdis; }e[N<<1];
inline void Add(int u,int v,int w) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; e[maxE].rdis=w; }
void DFS(int x,int fa)
{
	dep[x]=dep[fa]+1;
	st[++tot][0]=x;
	id[x]=tot;
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		DFS(v,x);
		st[++tot][0]=x;
	}
}
inline int Min(int x,int y) { return dep[x]<dep[y]?x:y; }
inline pair<int,int> LCA(int x,int y)
{
	int X=x, Y=y;
	x=id[x], y=id[y];
	if(x>y) swap(x,y);
	int k=lg[y-x+1];
	int lca=Min(st[x][k],st[y-(1<<k)+1][k]);
	return mk(lca,dep[X]+dep[Y]-dep[lca]*2);
}
inline void Init()
{
	phi[1]=mu[1]=1;
	for(ri int i=2;i<N;i++)
	{
		if(!book[i]) pri[++cnt]=i, phi[i]=i-1, mu[i]=-1;
		for(ri int j=1;j<=cnt&&i*pri[j]<N;j++)
		{
			book[i*pri[j]]=1;
			if(i%pri[j]) phi[i*pri[j]]=phi[i]*(pri[j]-1), mu[i*pri[j]]=-mu[i];
			else { phi[i*pri[j]]=phi[i]*pri[j]; break; }
		}
	}
	DFS(1,0);
	lg[0]=-1;
	for(ri int i=1;i<=tot;i++) lg[i]=lg[i>>1]+1;
	for(ri int i=1;(1<<i)<=tot;i++)
	for(ri int j=1;j+(1<<i)-1<=tot;j++)
	st[j][i]=Min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
inline bool cp(int x,int y) { return id[x]<id[y]; }
void DFS1(int x)
{
	if(book[x]) g[x]=phi[a[x]], now=(now+1ll*g[x]*dep[x]%Mod)%Mod;
	else g[x]=0;
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		DFS1(v);
		(g[x]+=g[v])%=Mod;
	}
}
void DFS2(int x,int W)
{
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		int tra=(W+1ll*(g[1]-2ll*g[v]%Mod+Mod)*e[i].rdis%Mod)%Mod;
		if(book[v]) res=(res+1ll*tra*phi[a[v]]%Mod)%Mod;
		DFS2(v,tra);
	}
}
signed main()
{
	n=read();
	for(ri int i=1;i<=n;i++)
	{
		a[i]=read();
		for(ri int j=1;j*j<=a[i];j++)
		{
			if(a[i]%j) continue;
			q[j].eb(i);
			if(j*j!=a[i]) q[a[i]/j].eb(i);
		}
	}
	for(ri int i=1;i<n;i++)
	{
		int u,v;
		u=read(), v=read();
		Add(u,v,1), Add(v,u,1);
	}
	dep[0]=-1;
	Init();
	memset(book,0,sizeof(book));
	for(ri int i=1;i<=n;i++)
	{
		if((int)q[i].size()<=1) continue;
		sort(q[i].begin(),q[i].end(),cp);
		for(auto j:q[i]) book[j]=1;
		res=0;
		sta[tp=1]=1, head[1]=0, maxE=0;
		for(auto j:q[i])
		{
			if(j==1) continue;
			pair<int,int> pp=LCA(j,sta[tp]);
			if(pp.fi!=sta[tp])
			{
				while(id[pp.fi]<id[sta[tp-1]])
				{
					pair<int,int> gg=LCA(sta[tp-1],sta[tp]);
					Add(sta[tp-1],sta[tp],gg.se);
					tp--;
				}
				if(id[pp.fi]>id[sta[tp-1]])
				{
					pair<int,int> gg=LCA(pp.fi,sta[tp]);
					head[pp.fi]=0;
					Add(pp.fi,sta[tp],gg.se), sta[tp]=pp.fi;
				}
				else Add(pp.fi,sta[tp],LCA(pp.fi,sta[tp]).se), tp--;
			}
			head[j]=0, sta[++tp]=j;
		}
		for(ri int j=1;j<tp;j++) Add(sta[j],sta[j+1],LCA(sta[j],sta[j+1]).se);
		DFS1(1);
		if(book[1]) res=1ll*now*phi[a[1]]%Mod;
		DFS2(1,now);
		F[i]=res;
		for(auto j:q[i]) book[j]=0; now=res=0;
	}
	for(ri int i=1;i<=n;i++)
	{
		res=0;
		for(ri int j=1;j<=n/i;j++)
		{
			if(!mu[j]) continue;
			if(~mu[j]) res=(res+F[i*j])%Mod;
			else res=(res-F[i*j]+Mod)%Mod;
		}
		ans=(ans+1ll*res*i%Mod*ksc(phi[i],Mod-2)%Mod)%Mod;
	}
	printf("%d\n",1ll*ans*ksc(n,Mod-2)%Mod*ksc(n-1,Mod-2)%Mod);
	return 0;
}
posted @ 2021-04-30 16:07  zkdxl  阅读(46)  评论(2编辑  收藏  举报