[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;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。