【BZOJ3451】Normal (点分治)

题面

BZOJ

题解

显然考虑每个点的贡献。但是发现似乎怎么算都不好计算其在点分树上的深度。

那么考虑一下这个点在点分树中每一次被计算的情况,显然就是其在某个点的点分树内时才会被计算答案。

那么设\(p[i][j]\)表示\(i\)在\(j\)的点分树里面的概率。

那么答案就变成了\(\sum_i\sum_j p[i][j]\)

那么\(i\)在\(j\)的点分树的概率显然就是两点之间路径不被断开的概率,即\(\frac{1}{dis(i,j)+1}\)。

那么点分治+\(FFT\)统计即可。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define MAX 70000
const double Pi=acos(-1);
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Complex{double a,b;}A[MAX],B[MAX],W[MAX];
Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.b*b.a+a.a*b.b};}
int r[MAX];
void FFT(Complex *P,int N,int opt)
{
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
for(int p=i<<1,j=0;j<N;j+=p)
for(int k=0;k<i;++k)
{
Complex w=W[N/i*k];w.b*=opt;
Complex X=P[j+k],Y=P[i+j+k]*w;
P[j+k]=X+Y;P[i+j+k]=X-Y;
}
if(opt==-1)for(int i=0;i<N;++i)P[i].a/=N;
}
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 size[MAX],rt,mx,Size;
bool vis[MAX];
void Getroot(int u,int ff)
{
size[u]=1;int ret=0;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff||vis[v])continue;
Getroot(v,u);size[u]+=size[v];
ret=max(ret,size[v]);
}
ret=max(ret,Size-size[u]);
if(mx>ret)mx=ret,rt=u;
}
int Ans[MAX];
int t[MAX],s[MAX],ln[MAX],md;
void dfs(int u,int ff,int dep)
{
t[dep]+=1;md=max(md,dep);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff||vis[v])continue;
dfs(v,u,dep+1);
}
}
void Multi(int *a,int *b,int n,int m,int *c)
{
int N,l=0;for(N=1;N<=n+m;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=1;i<N;i<<=1)
for(int k=0;k<i;++k)
W[N/i*k]=(Complex){cos(Pi/i*k),sin(Pi/i*k)};
for(int i=0;i<=n;++i)A[i].a=a[i];
for(int i=0;i<=m;++i)B[i].a=b[i];
FFT(A,N,1);FFT(B,N,1);
for(int i=0;i<N;++i)A[i]=A[i]*B[i];
FFT(A,N,-1);
for(int i=0;i<=n+m;++i)c[i]=A[i].a+0.5;
for(int i=0;i<N;++i)A[i]=B[i]=(Complex){0,0};
}
void Divide(int u)
{
vis[u]=true;int mxd=0;
s[0]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(vis[v])continue;
md=0;dfs(e[i].v,u,1);
Multi(s,t,mxd,md,ln);
for(int i=0;i<=mxd+md;++i)Ans[i]+=ln[i],ln[i]=0;
for(int i=0;i<=md;++i)s[i]+=t[i],t[i]=0;
mxd=max(mxd,md);
}
for(int i=0;i<=mxd;++i)s[i]=0;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(vis[v])continue;
Size=mx=size[v];Getroot(v,u);
Divide(rt);
}
}
int n;double ans;
int main()
{
n=read();
for(int i=1;i<n;++i)
{
int u=read()+1,v=read()+1;
Add(u,v);Add(v,u);
}
int N;for(N=1;N<=n;N<<=1);
for(int i=1;i<N;i<<=1)
for(int k=0;k<i;++k)
W[N/i*k]=(Complex){cos(Pi/i*k),sin(Pi/i*k)};
Size=mx=n;Getroot(1,0);Divide(rt);
for(int i=1;i<=n;++i)ans+=1.0*Ans[i]/(i+1);
ans*=2;ans+=n;
printf("%.4lf\n",ans);
return 0;
}

【BZOJ3451】Normal (点分治)的更多相关文章

  1. [BZOJ3451]normal 点分治,NTT

    [BZOJ3451]normal 点分治,NTT 好久没更博了,咕咕咕. BZOJ3451权限题,上darkbzoj交吧. 一句话题意,求随机点分治的期望复杂度. 考虑计算每个点对的贡献:如果一个点在 ...

  2. [BZOJ3451]Normal(点分治+FFT)

    [BZOJ3451]Normal(点分治+FFT) 题面 给你一棵 n个点的树,对这棵树进行随机点分治,每次随机一个点作为分治中心.定义消耗时间为每层分治的子树大小之和,求消耗时间的期望. 分析 根据 ...

  3. 【BZOJ3451】Tyvj1953 Normal 点分治+FFT+期望

    [BZOJ3451]Tyvj1953 Normal Description 某天WJMZBMR学习了一个神奇的算法:树的点分治!这个算法的核心是这样的:消耗时间=0Solve(树 a) 消耗时间 += ...

  4. BZOJ3451 Tyvj1953 Normal 点分治 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3451.html 题目传送门 - BZOJ3451 题意 给定一棵有 $n$ 个节点的树,在树上随机点分 ...

  5. BZOJ3451 Normal 期望、点分治、NTT

    BZOJCH传送门 题目大意:给出一棵树,求对其进行随机点分治的复杂度期望 可以知道一个点的贡献就是其点分树上的深度,也就是这个点在点分树上的祖先数量+1. 根据期望的线性性,考虑一个点对\((x,y ...

  6. [BZOJ3451][Tyvj1953]Normal(点分治+FFT)

    https://www.cnblogs.com/GXZlegend/p/8611948.html #include<cmath> #include<cstdio> #inclu ...

  7. 【BZOJ3451】Tyvj1953 Normal - 点分治+FFT

    题目来源:NOI2019模拟测试赛(七) 非原题面,题意有略微区别 题意: 吐槽: 心态崩了. 好不容易场上想出一题正解,写了三个小时结果写了个假的点分治,卡成$O(n^2)$ 我退役吧. 题解: 原 ...

  8. bzoj3451 Normal

    题意:点分治每次随机选重心,求期望复杂度. 发现一次点分治的复杂度就是点分树上每个节点的子树大小之和.(并没有发现......) 看这个. 注意这个写法有问题,随便来个菊花图就是n2了. 每一层点分治 ...

  9. 3451: Tyvj1953 Normal 点分治 FFT

    国际惯例的题面:代价理解为重心和每个点这个点对的代价.根据期望的线性性,我们枚举每个点,计算会产生的ij点对的代价即可.那么,i到j的链上,i必须是第一个被选择的点.对于i来说,就是1/dis(i,j ...

  10. BZOJ 3451: Tyvj1953 Normal 点分治+FFT

    根据期望的线性性,我们算出每个点期望被计算次数,然后进行累加. 考虑点 $x$ 对点 $y$ 产生了贡献,那么说明 $(x,y)$ 之间的点中 $x$ 是第一个被删除的. 这个期望就是 $\frac{ ...

随机推荐

  1. 【kindle笔记】之 《犬夜叉》-2017-12-26

    [kindle笔记]读书记录-总 2017-12-26 <犬夜叉> 买kindle的初衷是看计算机工具书看得眼快瞎了,我弟弟推荐给我的Linux系列<鸟叔私房菜> 真的是深思熟 ...

  2. Git的配置与使用

    Git的配置与使用 一,未配置过git 1.1,安装Git https://git-for-windows.github.io/ 1,2,鼠标右键点击Git Bash Here 1.3,输入命令 cd ...

  3. hangfire使用笔记

    1.导入nuget包 2.配置 简单配置后就可以写自己的Job了 注意:Hangfire.RecurringJobExtensions这个扩展支持两种job添加方法:json配置文件和特性.但由于时区 ...

  4. if判断条件注意!!!

    if(condition){ console.log(condition为true才执行): } 实际上会对condition执行Boolean()转型函数,将其转换成布尔值

  5. 3 Asking for more information

    1 Could you tell me more about your idea? 2 Could I hear more about your idea? 3 Could you expain yo ...

  6. Mybatis测试用例

    package cn.zhangxueliang.mybatis.mapper; import static org.junit.Assert.*; import java.io.InputStrea ...

  7. CLOUD计算产品成本嵌套

    1.产品入库单入库的半成品A (无单价) 2.其他出库单上(共耗的)出库的半成品A(无单价) 不管在同车间还是不同车间内都是认定为嵌套的,所以可以计算2遍成本,第1遍不考虑嵌套,第2遍就能计算进去了.

  8. HTML4到HTML5

    第一步: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0.1//EN" "http://www.w3.org/TR/html ...

  9. Redis五大数据类型

    首先说明下,Redis是:单线程+多路IO复用技术!!! string set  >  key  +  zset          list hash 常用的几个命令: >keys * 查 ...

  10. linux audit审计(7)--读懂audit日志

    让我们先来构造一条audit日志.在home目录下新建一个目录,然后配置一条audit规则,对这个目录的wrax,都记录审计日志: auditctl -w /home/audit_test -p wr ...