●Joyoi Normal
题链:
http://www.joyoi.cn/problem/tyvj-1953
题解:
定义d(u,v)这个函数,满足:
d(u,v)=1,当且仅当在点分树中,u是v的祖先
d(u,v)=0,其它情况
对于一个确定的点分树来说,
$\sum d(u,v)$就是答案。
但是现在点分树未知,我们再来考虑这个函数的取值
d(u,v)=1时必须满足u是v的祖先,
那么由于现在是随机的,所以对于u到v的这条链上的点,
u必须是第一个被随机为重心的点才能使得在点分树中,u是v祖先。
而这个概率是1/(dis(u,v)+1),
所以d(u,v)的期望取值就是1*1/(dis(u,v)+1)
即现在的问题变为求:$ANS=\sum 1/(dis(u,v)+1)$
那么必然要求出所有点对间的距离,所以采用点分治+FFT的做法。
对于分治的每一个重心,把整个子树dfs一遍,得到所有节点到重心的距离,
并得到一个数组A[i],表示子树中到重心距离为i的点数为A[i]个
然后让A数组自乘,做FFT,可以得到改子树内任意两个点经过重心的距离,
显然对于在同一个儿子子树里的两个点,也被统计了进去,所以再对重心的每个儿子做上述操作,然后减掉无效信息。
复杂度$O(Nlog^2N)$
代码:
#include<bits/stdc++.h>
#define MAXN 65540
using namespace std;
const double Pi=acos(-1);
double ANS,TIME;
bool vis[MAXN];
int size[MAXN];
int N,cnt;
struct Edge{
int ent;
int to[MAXN*2],nxt[MAXN*2],head[MAXN];
Edge(){ent=2;}
void Adde(int u,int v){
to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
}
}E;
struct Cpx{
double R,I;
Cpx(){}
Cpx(double _R,double _I):R(_R),I(_I){}
Cpx operator - () const{return Cpx(-R,-I);}
Cpx operator + (const Cpx &rtm) const{return Cpx(R+rtm.R,I+rtm.I);}
Cpx operator - (const Cpx &rtm) const{return *this+(-rtm);}
Cpx operator * (const Cpx &rtm) const{return Cpx(R*rtm.R-I*rtm.I,R*rtm.I+I*rtm.R);}
Cpx operator / (const double k) const{return Cpx(R/k,I/k);}
}A[MAXN];
namespace FFT{
int order[MAXN];
int Init(int _n){
static int n,len;
for(n=1,len=0;n<=2*_n;n<<=1) len++;
for(int i=0;i<n;i++) order[i]=(order[i>>1]>>1)|((i&1)<<(len-1));
return n;
}
void Fft(Cpx *Y,int n,int sign){
// static double timebefore; timebefore=1.0*clock()/CLOCKS_PER_SEC;
for(int i=0;i<n;i++) if(i<order[i]) swap(Y[i],Y[order[i]]);
for(int d=2;d<=n;d<<=1){
Cpx dw(cos(2*Pi/d),sin(sign*2*Pi/d)),w,tmp;
for(int i=0;w=Cpx(1,0),i<n;i+=d)
for(int k=i;k<i+d/2;w=w*dw,k++)
tmp=w*Y[k+d/2],Y[k+d/2]=Y[k]-tmp,Y[k]=Y[k]+tmp;
}
if(sign==-1) for(int i=0;i<n;i++) Y[i]=Y[i]/n;
// TIME+=1.0*clock()/CLOCKS_PER_SEC-timebefore;
}
}
void getroot(int u,int dad,int num,int &root,int &rootmax){
int umax=0; size[u]=0; cnt++;
for(int e=E.head[u];e;e=E.nxt[e]){
int v=E.to[e];
if(v==dad||vis[v]) continue;
getroot(v,u,num,root,rootmax);
size[u]+=size[v];
umax=max(umax,size[v]);
}
size[u]++; umax=max(umax,num-size[u]);
if(rootmax>umax) root=u,rootmax=umax;
}
void calc(int s,int dep,int sign){
static queue<int> Q;
static int dis[MAXN],reach[MAXN],tim,n;
Q.push(s); reach[s]=++tim; n=0;
dis[s]=dep; A[dis[s]].R+=1; n=dis[s];
while(!Q.empty()){
cnt++;
int u=Q.front(); Q.pop();
for(int e=E.head[u];e;e=E.nxt[e]){
int v=E.to[e];
if(reach[v]==tim||vis[v]) continue;
reach[v]=tim; dis[v]=dis[u]+1;
n=max(n,dis[v]); A[dis[v]].R++;
Q.push(v);
}
}
n=FFT::Init(n);
FFT::Fft(A,n,1);
for(int i=0;i<n;i++) A[i]=A[i]*A[i];
FFT::Fft(A,n,-1);
for(int i=1;i<n;i++)
ANS+=sign*A[i].R*1.0/(i+1),A[i]=Cpx(0,0);
ANS+=sign*A[0].R; A[0]=Cpx(0,0);
}
void solve(int u){
if(size[u]!=N) calc(u,1,-1);
int root=u,rootmax=size[u];
getroot(u,0,size[u],root,rootmax);
//cout<<rootmax<<endl;
vis[root]=1;
calc(root,0,1);
for(int e=E.head[root];e;e=E.nxt[e]){
int v=E.to[e]; if(vis[v]) continue;
if(size[v]>size[root]) size[v]=size[u]-size[root];
solve(v);
}
}
int main(){
ios::sync_with_stdio(0);
cin>>N;
for(int i=1,u,v;i<N;i++){
cin>>u>>v; u++; v++;
E.Adde(u,v); E.Adde(v,u);
}
size[1]=N; solve(1);
cout<<fixed<<setprecision(4)<<ANS<<endl;
//cout<<TIME<<" "<<cnt<<endl;
return 0;
}
●Joyoi Normal的更多相关文章
- CSharpGL(14)用geometry shader渲染模型的法线(normal)
+BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(14)用geometry shader渲染模型的法线(normal) +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 ...
- 一张图看懂normal,static,sealed,abstract 的 区别
+-------------------------+---+--------+--------+--------+----------+ | Class Type | | normal | stat ...
- 前端必须了解的布局常识:普通流(normal flow)
目录 一.概述 二.块级元素和内联元素 常见的块级元素 BFC 常见的行内元素 IFC 三.哪些情况会脱离普通流 浮动 绝对定位 固定定位 display:none 四.总结 五.参考资料 一.概述 ...
- What is a RaycastHit normal?
The normal is the direction pointing away from the collider it hits. http://answers.unity3d.com/ques ...
- Mysql索引PRIMARY、NORMAL、UNIQUE、FULLTEXT 区别和使用场合
索引 数据库的索引就像一本书的目录,能够加快数据库的查询速度. MYSQL索引有四种PRIMARY.INDEX.UNIQUE.FULLTEXT, 其中PRIMARY.INDEX.UNIQUE是一类,F ...
- [Unity3D] Normal map、Diffuse map 和 Speculer map
Normal map : Normal map (法线贴图) 它的作用是模拟出高模上的一些细节纹理,特别是将高模上的圆滑和粗糙度投射到低模上,让低模也有高模的效果. 因为高模的面数非常多,导入引擎后电 ...
- 【Normal Form】数据库表结构设计所遵从的范式
参考的优秀文章 数据库(第一范式,第二范式,第三范式) 数据库设计是件严肃.关键的事儿,一毕业,加入一个大型的行业项目,那儿的前辈资深工程师,就给我灌输数据库如何关键.神圣.深不可测的观念,所以,我一 ...
- Surface Normal Averaging
Surface Normal Averaging eryar@163.com 摘要Abstract:正确设置网格面上点的法向,对几何体在光照等情况下显示得更真实,这样就可以减少顶点数量,提高渲染速度. ...
- Surface Normal Vector in OpenCascade
Surface Normal Vector in OpenCascade eryar@163.com 摘要Abstract:表面上某一点的法向量(Normal Vector)指的是在该点处与表面垂直的 ...
随机推荐
- Beta 集合
Beta冲刺序列: Beta凡事预则立 :Beta No.0 Beta冲刺Day1:Beta No.1 Beta冲刺Day2:Beta No.2 Beta冲刺Day3:Beta No.3 Beta冲刺 ...
- 冲刺每日报告--Day1
敏捷冲刺每日报告--Day1 情况简介 由于李世钰同学出差了,周六才能回来.所以我们只能先写爬虫,封装代码提供接口等他回来调用. 任务进度 赵坤:编写了基本爬虫代码,目前能在国内有版权的B站.爱奇艺中 ...
- C语言——总结回顾
1.当初你是如何做出选择计算机专业的决定的?经过一个学期,你的看法改变了么,为什么? 你觉得计算机是你喜欢的领域吗,它是你擅长的领域吗? 为什么? 答:①当初选择计算机专业是出于一种选择,是一种带着冲 ...
- Archlinux无线联网教程
本人是学生党,故对于有线方式不甚了解,学校里一般使用mentohust用动态IP方式联网,或者直接连接wifi,这里介绍无线联网的一些方式,主要包括公共wifi和带有WEP或者WPA或者WPA2PSK ...
- Linux下I/O多路转接之select --fd_set
fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...
- app测试中遇到问题总结
工作总结: 1 这两天由于工作,需要进行抓包,使用了Charles,fidder,发现一个坑点: charles没有抓到返回值的时候,默认是不在列表显示请求信息的,能不能设置,我就不知道了,但是可以在 ...
- python 中os.path.join 双斜杠的解决办法
这两天在写东西的时候遇到了这个问题,主要是上传图片之后,无法在页面展示,原因就出在用join 拼接的路径中出现了"\"而造成的. >>> import os &g ...
- c 语言typedef 和 define的使用和区别
#define是C的指令,用于为各种数据类型定义别名,与typedef 类似,但是有一下几点不同 1,typedef仅限于为类型定义符号名称,而#define不仅可以为类型定义符号名称,也能为数值定义 ...
- GIT入门笔记(12)- 删除文件、提交删除和恢复删除
在Git中,删除也是一个修改操作,我们实战一下, 1.先添加add一个新文件test.txt到Git并且提交commit到本地版本库: $ git add test.txt$ git commit - ...
- global文件中的application_start方法中做: 定时器
<%@ Application Language="C#" %> <%@ import Namespace="System.Data" %&g ...