【CF809E】Surprise me!
这是一道神仙题
看到这样一个鬼畜的柿子
\]
又是树上距离又是\(\varphi\)的看起来根本就不知道怎么搞啊
首先需要知道一个这样的性质
\]
这个性质非常显然
设\(a=p^{k_1},b=p^{k_2},k_1<k_2\)
于是\(d=p^{k_1}\)
\]
\]
这个东西显然是积性的,扩展到多个质因子也是成立的
于是写成
\]
套路枚举\(gcd\)
\]
考虑设后面那个东西叫
\]
显然我们还需要一个函数叫
\]
我们可以直接反演了
\]
\]
现在的问题就是求出\(F\),我们就可以做了
显然树上的点都有一个约数\(d\)的时候,任意两点的的\(gcd\)就会是\(d\)的倍数
我们如果把\(d|a_i\)的\(i\)拿出来,建出一棵虚树,搞一个树形\(dp\)
求一下
\]
就好了,这就是一个小学生\(dp\)求树上带权重心了
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
const int maxn=2e5+5;
const LL mod=1e9+7;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt,w;}e[maxn<<1];
int dfn[maxn],son[maxn],deep[maxn],a[maxn],b[maxn],P[maxn];
int Top[maxn],st[maxn],num,n,__,top,head[maxn],fa[maxn];
int f[maxn],p[maxn>>1],mu[maxn],phi[maxn];
LL dp[maxn],sum[maxn],S,inv[maxn],F[maxn];
inline int cmp(int a,int b) {return dfn[a]<dfn[b];}
inline LL ksm(LL a,int b) {
LL S=1;
while(b) {if(b&1) S=S*a%mod;b>>=1;a=a*a%mod;}
return S;
}
inline void add(int x,int y,int w) {
e[++num].v=y;e[num].nxt=head[x];
head[x]=num;e[num].w=w;
}
void dfs1(int x) {
int maxx=-1;sum[x]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(deep[e[i].v]) continue;
deep[e[i].v]=deep[x]+1,fa[e[i].v]=x;
dfs1(e[i].v);sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
void dfs2(int x,int topf) {
Top[x]=topf;dfn[x]=++__;
if(!son[x]) return;
dfs2(son[x],topf);
for(re int i=head[x];i;i=e[i].nxt)
if(!Top[e[i].v]) dfs2(e[i].v,e[i].v);
}
inline int LCA(int x,int y) {
while(Top[x]!=Top[y]) {
if(deep[Top[x]]<deep[Top[y]]) std::swap(x,y);
x=fa[Top[x]];
}
if(deep[x]<deep[y]) return x;return y;
}
inline void ins(int x) {
if(top<=1) {st[++top]=x;return;}
int lca=LCA(st[top],x);
if(lca==st[top]) {st[++top]=x;return;}
while(top>1&&dfn[st[top-1]]>=dfn[lca])
add(st[top-1],st[top],deep[st[top]]-deep[st[top-1]]),top--;
if(lca!=st[top]) {add(lca,st[top],deep[st[top]]-deep[lca]);st[top]=lca;}
st[++top]=x;
}
void dfs(int x) {
sum[x]=f[x]*phi[a[x]];
for(re int i=head[x];i;i=e[i].nxt) {
dfs(e[i].v);
sum[x]+=sum[e[i].v];
dp[x]+=(dp[e[i].v]+sum[e[i].v]*(LL)e[i].w%mod)%mod;
dp[x]%=mod;
}
}
void reDfs(int x) {
for(re int i=head[x];i;i=e[i].nxt) {
LL now=dp[x]-(dp[e[i].v]+sum[e[i].v]*(LL)e[i].w%mod)%mod;
now=(now+mod)%mod;
dp[e[i].v]=(dp[e[i].v]+now+((S-sum[e[i].v])*(LL)e[i].w)%mod)%mod;
reDfs(e[i].v);
}
}
void clear(int x) {
f[x]=dp[x]=sum[x]=0;
for(re int i=head[x];i;i=e[i].nxt) clear(e[i].v);
head[x]=0;
}
int main() {
n=read();
for(re int i=1;i<=n;i++) a[i]=read();
for(re int x,y,i=1;i<n;i++)
x=read(),y=read(),add(x,y,0),add(y,x,0);
deep[1]=1,dfs1(1),dfs2(1,1);
for(re int i=1;i<=n;i++) b[a[i]]=i;
f[1]=mu[1]=phi[1]=1;
for(re int i=2;i<=n;i++) {
if(!f[i]) p[++p[0]]=i,mu[i]=-1,phi[i]=i-1;
for(re int j=1;j<=p[0]&&p[j]*i<=n;j++) {
f[p[j]*i]=1;
if(i%p[j]==0) {
phi[p[j]*i]=p[j]*phi[i];
break;
}
mu[p[j]*i]=-1*mu[i];
phi[p[j]*i]=(p[j]-1)*phi[i];
}
}
inv[1]=1;
for(re int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
for(re int k=1;k<=n;k++) {
int tot=0;
num=0,top=0;
for(re int j=k;j<=n;j+=k)
P[++tot]=b[j],f[P[tot]]=1;
std::sort(P+1,P+tot+1,cmp);
int rt=P[1];
for(re int i=2;i<=tot;i++) rt=LCA(rt,P[i]);
if(!f[rt]) st[++top]=rt;
for(re int i=1;i<=tot;i++) ins(P[i]);
while(top) add(st[top-1],st[top],deep[st[top]]-deep[st[top-1]]),top--;
dfs(rt);S=sum[rt];reDfs(rt);
for(re int i=1;i<=tot;i++)
F[k]=(F[k]+(LL)phi[a[P[i]]]*dp[P[i]]%mod)%mod;
clear(rt);
}
LL ans=0;
for(re int i=1;i<=n;i++) {
LL now=0;
for(re int j=i;j<=n;j+=i)
now=(now+F[j]*mu[j/i]%mod)%mod,now=(now+mod)%mod;
ans=(ans+now*(LL)i%mod*inv[phi[i]]%mod)%mod;
}
LL now=(LL)n*(LL)(n-1);
now%=mod;
printf("%lld\n",ksm(now,mod-2)*ans%mod);
return 0;
}
【CF809E】Surprise me!的更多相关文章
- 【CF809E】Surprise me!(动态规划,虚树,莫比乌斯反演)
[CF809E]Surprise me!(动态规划,虚树,莫比乌斯反演) 题面 洛谷 CodeForces 翻译: 给定一棵\(n\)个节点的树,每个点有一个权值\(a[i]\),保证\(a[i]\) ...
- 【CF809E】Surprise me! 树形DP 虚树 数学
题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...
- 【转】python f-string
[转]python f-string 文章目录 1. 主要内容 1.1. 旧时代的格式化字符串 1.1.1. Option #1: %-formatting 1.1.2. 怎样使用 %-forma ...
- 【Gabor】基于多尺度多方向Gabor融合+分块直方图的表情识别
Topic:表情识别Env: win10 + Pycharm2018 + Python3.6.8Date: 2019/6/23~25 by hw_Chen2018 ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
随机推荐
- Microsoft .NET Pet Shop 4: Migrating an ASP.NET 1.1 Application to 2.0
249 out of 297 rated this helpful - Rate this topic Gregory Leake Microsoft Corporation Alan Le, Ale ...
- JS 重写alert,使之能输出多个参数
windows._alert = windows.alert; windows.alert = function(){ _alert = (Array.prototype.slice(argument ...
- 写一个有字符界面的ssh链接工具
大概的样子 这是大致的样子- 写之前想说的 因为个人工作的的电脑是deepin系统的,系统本身的命令行非常好用,用第三方的ssh工具用不习惯,就想自己写一个. shell脚本是第一次写,写的不是很好, ...
- Linux线程同步——条件变量
互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的. 条件变量用来自动阻塞一个线程,直到某特殊情况发生为止. 通常条件变量和互斥锁同时使用. 和条件变量使用有关的几个重要函数: int p ...
- maven(视频学习)
一.maven的介绍 二.maven的环境搭建 三.maven的结构 四.maven常用的构建命令 五.maven自动创建目录骨架 六.maven中的坐标和仓库 七.在eclipse中安装maven插 ...
- Android开发之旅2:HelloWorld项目的目录结构
引言 前面Android开发之旅:环境搭建及HelloWorld,我们介绍了如何搭建Android开发环境及简单地建立一个HelloWorld项目,本篇将通过HelloWorld项目来介绍Androi ...
- front-end 前端发展学习路线参考图
front-end 前端发展学习路线参考图 学习的路程还很长~!
- Vue.js 的一些小技巧
给 props 属性设置多个类型 这个技巧在开发组件的时候用的较多,为了更大的容错性考虑,同时代码也更加人性化: export default { props: { width: { type: [S ...
- chrome跨域访问
这里设计到跨域访问的问题,如果非要在本地来访问,可以这是chrome的参数. 1.打开chrome快捷方式->属性 2.末尾添加: --args --disable-web-security 3 ...
- Laravel 支付宝支付异步通知
支付宝支付通知有前端通知(GET)和服务器异步通知(POST) 在配置支付宝支付时,需要注意的问题就是支付宝的回调操作: 1.在laravel中应该将支付宝通知路径组织csrf验证,否则会导致419错 ...