题解:

一道很套路的题目

首先一个结论

$\phi(xy)=\frac{\phi(x)*\phi(y)*gcd(x,y)}{\phi(gcd(x,y))}$

这个按照$\phi$的定义很容易知道

然后我们可以枚举gcd,很套路的可以莫比乌斯反演

然后变成给出k个点,求他们$\phi(x)*\phi(y)*dis(x,y)$

考虑所以gcd的点数为$\frac{n}{1}+\frac{n}{2}+\frac{n}{3}$=$nlogn$

于是我们需要一个与点数相关的算法

考虑虚树

之后有两种办法解决$\phi(x)*\phi(y)*dis(x,y)$

一种是考虑一个节点和它儿子节点的关系,那么就处理一下子树信息就行了

一种是把$dis(x,y)$写成$dis(x)+dis(y)-2*dis(lca(x,y))$然后dp一下

代码:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define ll long long
const int N=5e5;
const int mo=1e9+;
int a[N],head[N],dfn[N],cnt,p[N],pos[N],q[N],bz[][N],dep[N];
int f[N],phi[N],pri[N],prinum,ispri[N],n,l,miu[N],inv2;
bool tt[N];
struct re{
int a,b,c;
}e[N*];
int fsp(int x,int y)
{
ll ans=;
while (y)
{
if (y&) ans=ans*x%mo;
x=1ll*x*x%mo; y>>=;
}
return ans;
}
IL void plu(int &x,int y)
{
x=(x+y)%mo;
}
IL void arr(int x,int y)
{
e[++l].a=head[x];
e[l].b=y;
head[x]=l;
}
void dfs(int x,int y)
{
dfn[x]=++cnt; bz[][x]=y; dep[x]=dep[y]+;
for (rint u=head[x];u;u=e[u].a)
{
int v=e[u].b;
if (v!=y) dfs(v,x);
}
}
bool cmp(int x,int y)
{
return dfn[x]<dfn[y];
}
int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
dep(i,,) if (dep[bz[i][x]]>=dep[y]) x=bz[i][x];
if (x==y) return x;
dep(i,,) if (bz[i][x]!=bz[i][y]) x=bz[i][x],y=bz[i][y];
return bz[][x];
}
ll pp;
struct E{
int l,head[N],ans[N];
re e[N*];
IL void arr(int x,int y)
{
e[++l].a=head[x];
e[l].b=y;
e[l].c=x;
head[x]=l;
}
IL void clear()
{
rep(i,,l) head[e[i].c]=;
l=;
}
void dfs(int x)
{
ans[x]=phi[a[x]];
if (!tt[x])
{
ans[x]=;
}
ll ans2=;
for (rint u=head[x];u;u=e[u].a)
{
int v=e[u].b;
dfs(v);
ans[x]=(ans[x]+ans[v])%mo;
ans2+=1ll*ans[v]*ans[v];
}
ans2=(1ll*ans[x]*ans[x]-ans2)%mo;
pp=(pp+*dep[x]*ans2)%mo;
}
}E;
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
rep(i,,n) cin>>a[i],pos[a[i]]=i;
rep(i,,n-)
{
int x,y;
cin>>x>>y;
arr(x,y); arr(y,x);
}
dfs(,);
rep(i,,)
rep(j,,n)
bz[i][j]=bz[i-][bz[i-][j]];
miu[]=; phi[]=;
rep(i,,n)
{
if (!ispri[i]) {pri[++prinum]=i; miu[i]=-; phi[i]=i-;}
for (int j=;j<=prinum&&pri[j]*i<=n;j++)
{
ispri[i*pri[j]]=;
if (i%pri[j]==)
{
miu[i*pri[j]]=;
phi[i*pri[j]]=phi[i]*pri[j];
break;
} else miu[i*pri[j]]=-miu[i],phi[i*pri[j]]=phi[i]*(pri[j]-);
}
}
rep(i,,n)
{
int num=;
int ans=;
ll ans2=;
for (int j=;j*i<=n;j++) p[++num]=pos[i*j],plu(ans,phi[i*j]);
rep(j,,num) ans2=(ans2+1ll*phi[i*j]*dep[p[j]])%mo;
ans2=2ll*ans2*ans%mo;
sort(p+,p+num+,cmp);
rep(i,,num) tt[p[i]]=;
int h=,t=; q[h]=;
rep(i,,num)
{
while (h<t&&dep[lca(p[i],q[t])]<=dep[q[t-]])
{
E.arr(q[t-],q[t]); t--;
}
int k=lca(p[i],q[t]);
if (k!=q[t])
{
E.arr(k,q[t]); q[t]=k;
}
if (q[t]!=p[i]) q[++t]=p[i];
}
while (h<t)
{
E.arr(q[t-],q[t]); t--;
}
pp=;
E.dfs();
ans2=((ans2-pp)%mo+mo)%mo;
f[i]=ans2;
E.clear();
rep(i,,num) tt[p[i]]=;
}
ll ans2=;
rep(k,,n)
{
int ans=;
for (int j=;j*k<=n;j++)
{
plu(ans,miu[j]*f[j*k]);
}
ans2=(ans2+1ll*k*ans%mo*fsp(phi[k],mo-))%mo;
}
cout<<ans2*fsp(n,mo-)%mo*fsp(n-,mo-)%mo<<endl;
return ;
}

CF809E Surprise me!的更多相关文章

  1. CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))

    题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...

  2. CF809E Surprise me! 莫比乌斯反演、虚树

    传送门 简化题意:给出一棵\(n\)个点的树,编号为\(1\)到\(n\),第\(i\)个点的点权为\(a_i\),保证序列\(a_i\)是一个\(1\)到\(n\)的排列,求 \[ \frac{1} ...

  3. 仙人掌 && 圆方树 && 虚树 总结

    仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...

  4. 【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)

    [CF809E]Surprise me!(动态规划,虚树,莫比乌斯反演) 题面 洛谷 CodeForces 翻译: 给定一棵\(n\)个节点的树,每个点有一个权值\(a[i]\),保证\(a[i]\) ...

  5. 【CF809E】Surprise me! 树形DP 虚树 数学

    题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...

  6. 【CF809E】Surprise me!

    题目 这是一道神仙题 看到这样一个鬼畜的柿子 \[\sum_{i=1}^n\sum_{j=1}^n\varphi(a_i\times a_j)\times dis(i,j)\] 又是树上距离又是\(\ ...

  7. CF809E 【Surprise me!】

    我们要求的柿子是张这样子的: \[\frac{1}{n * (n - 1)} * \sum_{i = 1}^n\sum_{j = 1}^{n}\phi(a_i*a_j)*dis(i, j)\] 其中\ ...

  8. Surprise团队项目总结

    Surprise团队项目总结 项目实现情况 实现人人模式:2个用户在同一台电脑上进行切磋下棋,即实现五子棋游戏的基本功能 实现人机模式:初级模式已经实现,可以进行人机交互,但是还没达到智能判断下棋点 ...

  9. Surprise团队第四周项目总结

    Surprise团队第四周项目总结 项目进展 这周我们小组的项目在上周的基础上进行了补充,主要注重在注册登录界面的改进优化与美观,以及关于人计算法的学习与初步实现. 我们小组针对上次APP中界面出现的 ...

随机推荐

  1. 修改linux下yum镜像源为国内镜像

    修改为163yum源-mirrors.163.com 1.首先备份系统自带yum源配置文件/etc/yum.repos.d/CentOS-Base.repo [root@localhost ~]# m ...

  2. Hibernate对应关系(了解)

    布置的任务要用就写一下总结一下 hibernate有以下几种关系 一对一 一对多 多对一 多对多 首先这些对应关系是分单向和双向的 单向和双向有什么区别呢? 这个双向单向是面向对象的说法 意思就是你更 ...

  3. c/c++程序连接mysql

    1.libmysql.dll添加到System32文件夹 “regsvr32 libmysql.dll”注册 2.项目-->属性-->c/c++-->常规-->附加包含目录-- ...

  4. C#使用WindowsMediaPlayer实现视频播放

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  5. CentOS kickstart lvm

    install url --url=$tree text lang en_US.UTF- keyboard us timezone --utc Asia/Shanghai zerombr bootlo ...

  6. (N叉树 BFS) leetcode429. N-ary Tree Level Order Traversal

    Given an n-ary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  7. 实现select联动效果,数据从后台获取

    效果如下: 当type值选择完后,amount值会自动相应填入. 1. 从后台获取数据,为一个数组,里面包含多个对象. <select id="scholarshipTypeSelec ...

  8. MyISAM与InnoDB的区别是什么?

    1. 存储结构 MyISAM:每个MyISAM在磁盘上存储成三个文件.第一个文件的名字以表的名字开始,扩展名指出文件类型..frm文件存储表定义.数据文件的扩展名为.MYD (MYData).索引文件 ...

  9. 背包九讲PDF

    本资料仅限个人学习交流使用,不得用于商业用途. 背包九讲PDF:https://pan.baidu.com/s/17rTxMwCo9iSTOW77yucdXQ   提取码:xbqa

  10. H5_0006:JS判断PC,平板,手机平台的方法

    <script type="text/javascript"> //平台.设备和操作系统var system = { win: false, mac: false, x ...