【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前世今生”,以方便初学者能更 ...
随机推荐
- 神奇的datetime和datetime,一毫秒引发的血案
今天才发现C#的datetime和sqlserver的daetime是多么的不一样.首先最小和最大值不一样这是众所周知的,其实精度也是一大坑. 比如 DateTime.Today.AddMillise ...
- java的文件操作(1)
package com.test.file; import java.io.*; import java.util.ArrayList; import java.util.Date; import j ...
- 委托,匿名方法,lamda快速理解
转载于用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树 这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实 ...
- Dubbo安装及其实战1
一.Dubbo安装 (1)安装zk和tomcat yum 安装tomcat 默认路径为 /usr/share/tomcat zookeeper 我这里采用的是使用zookeeper管理的.所以要安装z ...
- Code Signal_练习题_Sort by Height
Some people are standing in a row in a park. There are trees between them which cannot be moved. You ...
- 微信小程序之雪碧图(css script)
今天有朋友问我关于微信小程序中如何在不占用大量网络带宽的情况下快速加载图片,我给他推荐了两种方式 1.雪碧图(css script),有过前端经验的朋友应该都有接触过. 2.懒加载. 由于时间关系我就 ...
- Android微信支付—注意事项
坑点一:PayReq的参数 sign的生成 PayReq对象有个参数为packageValue 而sign生成时要用到packageValue,但是对应的Key是package,这里的key容易弄错 ...
- git pull 错误:The following untracked working tree files would be overwritten by merge
错误描述: $ git pull origin alphaFrom https://github.com/shirley-wu/HeartTrace * branch alpha ...
- 精华阅读第 12 期 | 最新 App Store 审核指南与10大被拒理由?
很多时候,我们对技术的追求是没有止境的,我们需要不断的学习,进步,再学习,再进步!本文系移动精英开发俱乐部的第12期文章推荐阅读整理,其中涉及到了 Android 数据库框架,架构设计中的循环引用,同 ...
- Linux学习之CentOS(四)----Linux各目录的介绍
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...