Codeforces 809E: Surprise me!(Mobius反演)

传送门

题解:
对于每个 i i ,处理出: f i = a b [ ( v a l a , v a l b ) = = i ] φ ( v a l a ) φ ( v a l b ) d i s ( a , b ) f_i=\sum_a\sum_b[(val_a,val_b)==i]\varphi(val_a)\varphi(val_b)dis(a,b)

那么 a n s = i f i i φ ( i ) ans = \sum_i\frac{f_i i}{\varphi(i)}

先处理一个 g g
g i = i v a l a i v a l b φ ( a ) φ ( b ) d i s ( a , b ) g_i = \sum_{i|val_a}\sum_{i|val_b}\varphi(a)\varphi(b)dis(a,b)

这个可以点分治中枚举一下因数,时间复杂度 O ( n log 2 n ) O(n\log^2n)
那么显然 g n = n d f d g_n = \sum_{n|d}f_d

Mobius反演一下就行了,时间复杂度 O ( n log n ) O(n \log n)

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=2e5+50, mod=1e9+7;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int mul(int x,int y) {return (long long)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
int n,pr[N],npr[N],pt;
int mu[N],phi[N];
int val[N],s[2][N];
int vis[N],sze[N],mx,total,G;
int f[N],h[N];
vector <int> g[N];
vector <int> edge[N];

inline void sieve() {
	mu[1]=phi[1]=1;
	for(int i=2;i<=n;i++) {
		if(!npr[i]) {pr[++pt]=i; mu[i]=mod-1; phi[i]=i-1;}
		for(int j=1;j<=pt;j++) {
			int k=i*pr[j]; 
			if(k>n) break;
			npr[k]=1;
			if(i%pr[j]) {
				mu[k]=mod-mu[i];
				phi[k]=mul(phi[i],pr[j]-1);
			} else {
				mu[k]=0;
				phi[k]=phi[i]*pr[j];
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j+=i) g[j].push_back(i);
}
inline void calcG(int x,int f) {
	sze[x]=1; int mx_son=0;
	for(auto v:edge[x]) if(!vis[v] && v^f) {
		calcG(v,x); sze[x]+=sze[v];
		mx_son=max(mx_son,sze[v]);
	} mx_son=max(mx_son,total-sze[x]);
	if(mx>=mx_son) mx=mx_son, G=x;
}
inline int add(int x,int d,int t) {
	int v1=phi[x], v2=mul(phi[x],d);
	for(auto v:g[x])
		s[0][v]=add(s[0][v],mul(v1,t)), s[1][v]=add(s[1][v],mul(v2,t));
}
inline void ask(int x,int d) {
	int v1=phi[x], v2=mul(phi[x],d);
	for(auto v:g[x])
		f[v]=add(f[v],mul(s[0][v],v2)), f[v]=add(f[v],mul(s[1][v],v1));
}
inline void dfs1(int x,int d,int f) {
	ask(val[x],d); sze[x]=1;
	for(auto v:edge[x])
		if(!vis[v] && v^f)
			dfs1(v,d+1,x), sze[x]+=sze[v];
}
inline void dfs2(int x,int d,int flag,int f) {
	add(val[x],d,flag);
	for(auto v:edge[x])
		if(!vis[v] && v^f)
			dfs2(v,d+1,flag,x);
}
inline void solve(int x) {
	add(val[x],0,1);
	vis[x]=1;
	for(auto v:edge[x]) 
		if(!vis[v]) {
			dfs1(v,1,x); 
			dfs2(v,1,1,x);	
		}
	for(auto v:edge[x]) 
		if(!vis[v]) 
			dfs2(v,1,mod-1,x);
	add(val[x],0,mod-1);
	for(auto v:edge[x]) 
		if(!vis[v]) {
			mx=total=sze[v];
			calcG(v,x);
			solve(G);
		}
}
int main() {
	n=rd();	sieve();
	for(int i=1;i<=n;i++) val[i]=rd();
	for(int i=1;i<n;i++) {
		int x=rd(), y=rd();
		edge[x].push_back(y);
		edge[y].push_back(x);
	}
	mx=total=n;
	calcG(1,0); 
	solve(G);
	for(int i=n;i>=1;i--)
		for(int j=i;j<=n;j+=i)
			h[i]=add(h[i],mul(f[j],mu[j/i]));
	int ans=0;
	for(int i=1;i<=n;i++)
		ans=add(ans,mul(h[i],mul(i,power(phi[i],mod-2))));
	cout<<mul(ans,power(1ll*n*(n-1)/2%mod,mod-2))<<'\n';
}
发布了553 篇原创文章 · 获赞 227 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/84037197