CF809E Surprise me!
题解:
一道很套路的题目
首先一个结论
$\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!的更多相关文章
- CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))
题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...
- CF809E Surprise me! 莫比乌斯反演、虚树
传送门 简化题意:给出一棵\(n\)个点的树,编号为\(1\)到\(n\),第\(i\)个点的点权为\(a_i\),保证序列\(a_i\)是一个\(1\)到\(n\)的排列,求 \[ \frac{1} ...
- 仙人掌 && 圆方树 && 虚树 总结
仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...
- 【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_ ...
- 【CF809E】Surprise me!
题目 这是一道神仙题 看到这样一个鬼畜的柿子 \[\sum_{i=1}^n\sum_{j=1}^n\varphi(a_i\times a_j)\times dis(i,j)\] 又是树上距离又是\(\ ...
- CF809E 【Surprise me!】
我们要求的柿子是张这样子的: \[\frac{1}{n * (n - 1)} * \sum_{i = 1}^n\sum_{j = 1}^{n}\phi(a_i*a_j)*dis(i, j)\] 其中\ ...
- Surprise团队项目总结
Surprise团队项目总结 项目实现情况 实现人人模式:2个用户在同一台电脑上进行切磋下棋,即实现五子棋游戏的基本功能 实现人机模式:初级模式已经实现,可以进行人机交互,但是还没达到智能判断下棋点 ...
- Surprise团队第四周项目总结
Surprise团队第四周项目总结 项目进展 这周我们小组的项目在上周的基础上进行了补充,主要注重在注册登录界面的改进优化与美观,以及关于人计算法的学习与初步实现. 我们小组针对上次APP中界面出现的 ...
随机推荐
- dedecms安装操作-重安装-开启GD库
wamp5_1.7.4 打开:http://localhost/install/安装 (输入:域名/install,回车跳转到安装界面,勾选“我已经阅读并同意此协议”,然后点击“继续按钮”.) 重安装 ...
- JS学习笔记Day23
一.什么是Promise (一)Promise是ES6新增的解决异步(非阻塞)中存在的问题而产生的构造函数 二.Promise中的三种状态 pending(进行中) resoved(成功后) reje ...
- Python正则表达式指南(转)
目录 Python正则表达式指南(转) 0.防走丢 1. 正则表达式基础 1.1. 简单介绍 1.2. 数量词的贪婪模式与非贪婪模式 1.3. 反斜杠的困扰 1.4. 匹配模式 2. re模块 2.1 ...
- JAVA之锁-volatile
锁是JAVA多线程关键,也是面试中必问的, 在此好好总结一下. (先要从进程和线程说起,此处先欠下,回头专门说一下操作系统是怎么管理进程和线程的) 说到多线程就要说说JAVA的内存模型:图片来自于网络 ...
- 实现IOC功能的简单Spring框架
需求分析 设计一个含有IOC的简单Spring,要求含有对象注册.对象管理以及暴露给外部的获取对象功能. 项目设计 对于注册的对象用一个类BeanInfo来描述其信息,包括对象标识.全类名以及属性名与 ...
- Linux进程管理工具Supervisor
简述 Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启. 它是通过fork/exec的方式把这些被管 ...
- python放弃篇(Django/爬虫)
第一篇:Django系列 第二篇:爬虫系列 待续……
- ArcGis使用字段别名Alias Name导出Excel
在ArcMap10.3+(根据官网描述应该是,作者测试使用10.5,可行)以后的版本,可以使用ArcToolbox工具导出Excel. 工具位置ConversionTools——Excel——Tabl ...
- “不能在dropdownlist中选择多个项
DropDownList.ClearSelection(); DropDownList.SelectedItem.Text = "value值";
- C# 泛型单例
不支持非公共的无参构造函数的 public abstract class BaseInstance<T> where T : class,new() { private readonly ...