【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)
【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)
题面
洛谷
CodeForces
翻译:
给定一棵\(n\)个节点的树,每个点有一个权值\(a[i]\),保证\(a[i]\)是一个\(1..n\)的排列。
求$$\frac{1}{n(n-1)}\sum_{i=1}n\sum_{j=1}n\varphi(a_i*a_j)·dist(i,j)$$
其中,\(\varphi(x)\)是欧拉函数,\(dist(i,j)\)表示\(i,j\)两个节点在树上的距离。
题解
神题啊。。。
首先来个轻松而有趣的结论
\(\varphi(a*b)=\varphi(a)*\varphi(b)*\frac{d}{\varphi(d)}\),其中,\(d=gcd(a,b)\)
证明?大力分解质因数就好啦
现在我们来推式子(好久没有推过式子啦)
先不管前面那个东西
Ans&=\sum_{i=1}^n\sum_{j=1}^n\varphi(a_i)\varphi(a_j)\frac{gcd(a_i,a_j)}{\varphi(gcd(a_i,a_j)}dist(i,j)\\
&=\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{i=1}^n\sum_{j=1}^n[gcd(a_i,a_j)=d]\varphi(a_i)\varphi(a_j)dist(i,j)\\
\end{aligned}
\]
这样的东西很舒服啊
设$$g(d)=\sum_{i=1}n\sum_{j=1}n[gcd(a_i,a_j)=d]\varphi(a_i)\varphi(a_j)dist(i,j)$$
设$$f(d)=\sum_{i=1}n\sum_{j=1}n[d|gcd(a_i,a_j)]\varphi(a_i)\varphi(a_j)dist(i,j)$$
然后莫比乌斯反演就可以用啦
\]
现在只需要求解\(f(i)\)
接着推式子
&=\sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{d|i}\mu(\frac{i}{d})f(i)\\
f(d)&=\sum_{i=1}^n\sum_{j=1}^n[d|gcd(a_i,a_j)]\varphi(a_i)\varphi(a_j)dist(i,j)\\
&=\sum_{i=1}^n\sum_{j=1}^n[d|gcd(a_i,a_j)]\varphi(a_i)\varphi(a_j)(dep_i+dep_j-2*dep_{lca})
\end{aligned}
\]
我们发现,对于\(d|gcd(a_i,a_j)\)的所有\(i,j\)
相当于满足\(a_i,a_j\)是\(d\)的倍数
如果只是求前面的两项只与自身有关的\(dep_i+dep_j\),
这个问题就非常好解。
但是现在多了一个\(dep_{lca}\) 。
因此我们需要做\(dp\)。
把所有\(d|a_i\)的点全部拿下来建立虚树,在虚树上\(dp\)就好了。。。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 222222
#define MOD 1000000007
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int fpow(int a,int b)
{
int s=1;
while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
return s;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int a[MAX],b[MAX],n;
int phi[MAX],mu[MAX],pri[MAX],tot;
bool zs[MAX];
void pre(int N)
{
zs[1]=true;phi[1]=mu[1]=1;
for(int i=2;i<=N;++i)
{
if(!zs[i])pri[++tot]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=tot&&i*pri[j]<=N;++j)
{
zs[i*pri[j]]=true;
if(i%pri[j])phi[i*pri[j]]=phi[i]*phi[pri[j]],mu[i*pri[j]]=-mu[i];
else{mu[i*pri[j]]=0,phi[i*pri[j]]=phi[i]*pri[j];break;}
}
}
}
int dfn[MAX],low[MAX],size[MAX],hson[MAX],top[MAX],fa[MAX],tim,dep[MAX];
void dfs1(int u,int ff)
{
fa[u]=ff;dep[u]=dep[ff]+1;size[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
dfs1(v,u);size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim;
if(hson[u])dfs2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=fa[u]&&e[i].v!=hson[u])
dfs2(e[i].v,e[i].v);
low[u]=tim;
}
int LCA(int u,int v)
{
while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
return dep[u]<dep[v]?u:v;
}
bool cmp(int a,int b){return dfn[a]<dfn[b];}
int ans=0,K,p[MAX<<1],S[MAX],f[MAX];
bool vis[MAX];
void Plus(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
void DP(int u)
{
f[u]=vis[u]?phi[a[u]]:0;
Plus(ans,MOD-1ll*f[u]*f[u]%MOD*dep[u]%MOD);
for(int i=h[u];i;i=e[i].next)
{
DP(e[i].v);
Plus(ans,MOD-2ll*f[u]*f[e[i].v]%MOD*dep[u]%MOD);
Plus(f[u],f[e[i].v]);
}
}
int F[MAX],G[MAX];
int main()
{
n=read();pre(n);
for(int i=1;i<=n;++i)a[i]=read(),b[a[i]]=i;
for(int i=1;i<n;++i)
{
int u=read(),v=read();
Add(u,v);Add(v,u);
}
dfs1(1,0);dfs2(1,1);
memset(h,0,sizeof(h));
for(int T=1;T<=n;++T)
{
K=n/T;int s1=0,s2=0;cnt=1;
for(int i=1;i<=K;++i)p[i]=b[i*T];
for(int i=1;i<=K;++i)
Plus(s1,phi[a[p[i]]]),Plus(s2,1ll*dep[p[i]]*phi[a[p[i]]]%MOD);
for(int i=1;i<=K;++i)vis[p[i]]=true;
sort(&p[1],&p[K+1],cmp);
for(int i=K;i>1;--i)p[++K]=LCA(p[i],p[i-1]);
sort(&p[1],&p[K+1],cmp);K=unique(&p[1],&p[K+1])-p-1;
for(int i=1,tp=0;i<=K;++i)
{
while(tp&&low[S[tp]]<dfn[p[i]])--tp;
Add(S[tp],p[i]);S[++tp]=p[i];
}
DP(p[1]);Plus(ans,ans);
Plus(ans,2ll*s1*s2%MOD);
for(int i=1;i<=K;++i)h[p[i]]=0,vis[p[i]]=false;
F[T]=ans;ans=0;
}
for(int i=1;i<=n;++i)
for(int j=i;j<=n;j+=i)
if(mu[j/i]!=0)Plus(G[i],(mu[j/i]==1)?F[j]:(MOD-F[j]));
for(int i=1;i<=n;++i)G[i]=1ll*G[i]*i%MOD*fpow(phi[i],MOD-2)%MOD;
for(int i=1;i<=n;++i)Plus(ans,G[i]);
ans=1ll*ans*fpow(n,MOD-2)%MOD*fpow(n-1,MOD-2)%MOD;
printf("%d\n",ans);
return 0;
}
【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)的更多相关文章
- Codeforces 809E - Surprise me!(虚树+莫比乌斯反演)
Codeforces 题目传送门 & 洛谷题目传送门 1A,就 nm 爽( 首先此题一个很棘手的地方在于贡献的计算式中涉及 \(\varphi(a_ia_j)\),而这东西与 \(i,j\) ...
- CF809E Surprise me! 莫比乌斯反演、虚树
传送门 简化题意:给出一棵\(n\)个点的树,编号为\(1\)到\(n\),第\(i\)个点的点权为\(a_i\),保证序列\(a_i\)是一个\(1\)到\(n\)的排列,求 \[ \frac{1} ...
- 【Codeforces 809E】Surprise me!(莫比乌斯反演 & 虚树)
Description 给定一颗 \(n\) 个顶点的树,顶点 \(i\) 的权值为 \(a_i\).求: \[\frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n\var ...
- Codeforces.809E.Surprise me!(莫比乌斯反演 虚树)
题目链接 \(Description\) 给定一棵树,求\[\frac{1}{n(n-1)/2}\times\sum_{i\in[1,n],j\in[1,n],i\neq j}\varphi(a_i\ ...
- CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))
题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...
- 【CF809E】Surprise me! 树形DP 虚树 数学
题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...
- YbtOJ#723-欧拉之树【莫比乌斯反演,虚树】
正题 题目链接:http://www.ybtoj.com.cn/contest/121/problem/2 题目大意 给出\(n\)个点的一棵树,每个点有一个权值\(a_i\),求 \[\sum_{i ...
- bzoj3529(莫比乌斯反演+离线+树状数组)
在你以为理解mobus的时候,苦苦想通过化简公式来降低复杂度时,这题又打了我一巴掌. 看来我并没有理解到acmicpc比赛的宗旨啊. 这么多次查询可以考虑离线操作,使用树状数组单点更新. /***** ...
- 【BZOJ3529】数表(莫比乌斯反演,树状数组)
[BZOJ3529]数表(莫比乌斯反演,树状数组) 题解 首先不管\(A\)的范围的限制 要求的东西是 \[\sum_{i=1}^n\sum_{j=1}^m\sigma(gcd(i,j))\] 其中\ ...
随机推荐
- React-将元素渲染到 DOM 中
首先我们在一个 HTML 页面中添加一个 id="root" 的 <div>,在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为 “根” ...
- 重装系统之无法在驱动器0的分区1上安装windows
在通过U盘或光盘安装win8/win8.1/win10 时,遇到无法安装的问题,提示“无法在驱动器0的分区1上安装windows”,格式化分区也不能解决,进而提示Windows无法安装到这个磁盘,选中 ...
- Codeforces 987E Petr and Permutations(数组的置换与复原 、结论)
题目连接: Petr and Permutations 题意:给出一个1到n的序列,Petr打乱了3n次,Um_nik打乱了7n+1次,现在给出被打乱后的序列,求是谁打乱的. 题解:因为给出了一个3* ...
- Python 学习 第六篇:迭代和解析
Python中的迭代是指按照元素的顺序逐个调用的过程,迭代概念包括:迭代协议.可迭代对象和迭代器三个概念. 迭代协议是指有__next__()函数的对象会前进到下一个结果,而到达系列的末尾时,则会引发 ...
- elaticsear no [query] registered for [filtered] 错误
1.问题描述 执行语句: GET /megacorp/employee/_search { "query" : { "filtered" : { "f ...
- 使用IdentityServer4实现一个简单的Oauth2客户端模式授权
1.首先新建一个webAPI项目做为IdentityServer的服务端,提供生成Token的服务,首先修改Startup.cs文件,如下图: 2.增加一个Config.cs文件,以便于提供资源和认证 ...
- 做完小程序项目、老板给我加了5k薪资~
大家好,我是苏南,今天要给大家分享的是最近公司做的一个小程序项目,过程中的一些好的总结和遇到的坑,希望能给其他攻城狮带来些许便利,更希望能做完之后老板给你加薪- 今天是中秋节的第一天,假日的清晨莫名的 ...
- 用EXCLE群发outlook邮件
Outlookでメール一括送信する方法(差し込み.HTML形式.添付ファイル複数あり) メールを一括送信する方法はウェブ上にいくつも紹介されていましたが.以下のすべての条件を満たすものが見つからなかっ ...
- 第十次Scrum meeting
第十次Scrum meeting 任务及完成度: 成员 1.2 1.3 陈谋 任务1040:完成stackoverflow的数据处理后的json处理(100%) 任务1114-2:完成对pdf.pp ...
- linux内核分析第五次实验
给MenuOS增加time和time-asm命令 上周是从用户态的观点来理解系统调用,这周从内核态出发研究系统调用,通过跟踪调试,首先把上周的两个命令加到MenuOS中: rm menu -rf 强制 ...