题目描述

  \(\forall 0\leq i<n\),求有多少棵\(n\)个点,权值和优先级完全随机的treap的树高为\(i\)。

  \(n\leq 30000\)

题解

  设\(f_{i,j}\)为\(j\)个点的树,树高不超过为\(i\)的概率

\[f_{i,j}=\frac{1}{j}\sum_{k=1}^{j}f_{i-1,j-1}\times f_{i-1,j-k}
\]

  枚举一个点左子树大小\(k-1\),那么右子树大小为\(j-k\)。且这个点的优先级为这\(j\)个点最小的概率是\(\frac{1}{j}\)。

  这个东西是个卷积,可以用FFT加速。

  其实期望树高是\(O(\log n)\)的。实际上只有前面一部分的答案不为\(0\)。所以我们只用计算树高\(\leq 100\)的答案。

  时间复杂度:\(O(n\log^2n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
double pi=acos(-1);
struct cp
{
double x,y;
cp(double a=0,double b=0)
{
x=a;
y=b;
}
};
cp operator +(cp a,cp b)
{
return cp(a.x+b.x,a.y+b.y);
}
cp operator -(cp a,cp b)
{
return cp(a.x-b.x,a.y-b.y);
}
cp operator *(cp a,cp b)
{
return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
cp operator /(cp a,double b)
{
return cp(a.x/b,a.y/b);
}
namespace fft
{
cp w1[100010];
cp w2[100010];
int rev[100010];
int n;
void init(int m)
{
n=1;
while(n<=m)
n<<=1;
int i;
for(i=2;i<=n;i<<=1)
{
w1[i]=cp(cos(2*pi/i),sin(2*pi/i));
w2[i]=cp(cos(2*pi/i),-sin(2*pi/i));
}
rev[0]=0;
for(i=1;i<n;i++)
rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
}
void fft(cp *a,int t)
{
int i,j,k;
cp u,v,w,wn;
for(i=0;i<n;i++)
if(rev[i]<i)
swap(a[i],a[rev[i]]);
for(i=2;i<=n;i<<=1)
{
wn=(~t?w1[i]:w2[i]);
for(j=0;j<n;j+=i)
{
w=1;
for(k=j;k<j+i/2;k++)
{
u=a[k];
v=a[k+i/2]*w;
a[k]=u+v;
a[k+i/2]=u-v;
w=w*wn;
}
}
}
if(t==-1)
for(i=0;i<n;i++)
a[i]=a[i]/n;
}
}
cp a[100010];
double f[110][30010];
double ans[30010];
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
int n;
scanf("%d",&n);
int m=100;
int i,j;
fft::init(2*n);
a[0]=a[1]=1;
double last;
for(i=0;i<n;i++)
ans[i]=0;
last=ans[0]=a[n].x;
for(i=1;i<=m;i++)
{
fft::fft(a,1);
for(j=0;j<fft::n;j++)
a[j]=a[j]*a[j];
fft::fft(a,-1);
for(j=fft::n-1;j>=1;j--)
a[j]=a[j-1];
a[0]=a[1]=1;
for(j=2;j<=n;j++)
a[j]=a[j]/j;
for(j=n+1;j<fft::n;j++)
a[j]=0;
ans[i]=a[n].x-last;
last=a[n].x;
}
// for(i=0;i<=m;i++)
// f[i][1]=f[i][0]=1;
// for(i=1;i<=m;i++)
// for(j=2;j<=n;j++)
// for(k=1;k<=j;k++)
// f[i][j]+=f[i-1][k-1]*f[i-1][j-k]/j;
// for(i=0;i<=m;i++)
// {
// ans[i]=f[i][n];
// if(i>=1)
// ans[i]-=f[i-1][n];
// }
for(i=0;i<=n-1;i++)
printf("%.10lf\n",ans[i]);
return 0;
}

【XSY2332】Randomized Binary Search Tree 概率DP FFT的更多相关文章

  1. 【xsy2332】Randomized Binary Search Tree DP+FFT

    题目大意:给你一个$[0,1]$之间等概率随机序列,你需要把这个序列插入到一棵$treap$中,问这棵$treap$的期望深度,请对于$[1,n]$中的每个深度分别输出它的概率(实数,保留五位小数). ...

  2. 【未知来源】Randomized Binary Search Tree

    题意 求 \(n\) 个点的 Treap 深度为 \(h=0,1,2,\cdots,n\) 的概率. Treap 是一个随机二叉树,每个节点有权值和优先级,权值和优先级都是 \([0,1]\) 中的随 ...

  3. uva 10304 - Optimal Binary Search Tree 区间dp

    题目链接 给n个数, 这n个数的值是从小到大的, 给出个n个数的出现次数. 然后用他们组成一个bst.访问每一个数的代价是这个点的深度*这个点访问的次数. 问你代价最小值是多少. 区间dp的时候, 如 ...

  4. 笔试算法题(58):二分查找树性能分析(Binary Search Tree Performance Analysis)

    议题:二分查找树性能分析(Binary Search Tree Performance Analysis) 分析: 二叉搜索树(Binary Search Tree,BST)是一颗典型的二叉树,同时任 ...

  5. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  6. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  7. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  8. Leetcode: Convert sorted list to binary search tree (No. 109)

    Sept. 22, 2015 学一道算法题, 经常回顾一下. 第二次重温, 决定增加一些图片, 帮助自己记忆. 在网上找他人的资料, 不如自己动手. 把从底向上树的算法搞通俗一些. 先做一个例子: 9 ...

  9. [LeetCode] Closest Binary Search Tree Value II 最近的二分搜索树的值之二

    Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...

随机推荐

  1. NEST.net Client

    NEST.net Client For Elasticsearch简单应用 由于最近的一个项目中的搜索部分要用到 Elasticsearch 来实现搜索功能,苦于英文差及该方面的系统性资料不好找,在实 ...

  2. 快速为git添加一个用户

    环境:用gitosis-admin管理git的权限. 前期git环境的搭建略去,主要给出快速添加一个用户的步骤: 在git bash中用“ssh-keygen -t rsa”生成公钥私钥,默认放到 “ ...

  3. docker 修改port 端口

    修改docker容器端口映射的方法 - wesleyflagon的专栏 - CSDN博客https://blog.csdn.net/wesleyflagon/article/details/78961 ...

  4. Win1064位下mysql插入百万行数据耗时问题

    performance - Inserting 1 Million records is taking too much time MYSQL - Stack Overflowhttps://stac ...

  5. [转帖]迎战AMD 7nm 64核EPYC 英特尔至强也玩起了胶水以及性价比

    迎战AMD 7nm 64核EPYC 英特尔至强也玩起了胶水以及性价比 Intel 最强CPU 从最开始的双核 到现在的 28核 发展迅猛. https://www.cnbeta.com/article ...

  6. 使用NFS时的一些问题

    当我把nfs服务端共享目录/usr/local/data/test删掉时,在nfs客户端却没办法把之前挂载在这上面的当前从机上的/usr/local/data/test删除,出现 bash: cd: ...

  7. Day 4-2 time & datetime模块

    time模块. import time time.time() #输出: 1523195163.140625 time.localtime() # 获取的是操作系统的时间,可以添加一个时间戳参数 # ...

  8. C++中String类的字符串分割实现

    最近笔试,经常遇到需要对字符串进行快速分割的情景,主要是在处理输入的时候,而以前练习算法题或笔试,很多时候不用花啥时间考虑测试用例输入的问题.可是C++标准库里面没有像java的String类中提供的 ...

  9. hive之size函数和cast转换函数

    size返回map集合中元素的个数: cast函数将一种类型的数据转换成其他格式的数据

  10. composer 下载包慢的解决方法

    方法一: 修改 composer 的全局配置文件(推荐方式) 打开命令行窗口(windows用户)或控制台(Linux.Mac 用户)并执行如下命令: composer config -g repo. ...