题面

传送门

分析

由于期望的线性性,我们可以分别计算每个点对对答案的贡献

有三个人取数字,分开对每个人考虑

设每个人分别取了k个数,则一共有\(C_n^k\)种组合,选到每种组合的概率为\(\frac{1}{C_n^k}\)

对于一个幸运点对,包含它的组合有\(C_{n-2}^{k-2}\)种(k个点中有2个点是该点对,再从剩下的n-2个点中选k-2个点,每种的贡献均为1)

所以每一个点对的贡献是

\[\frac{C_{n-2}^{k-2}}{C_n^k}=\frac{\frac{(n-2)!}{(n-k)!\times (k-2)!}}{\frac{n!}{(n-k)! \times k !}}=\frac{(n-2)! \times k !}{n! \times (k-2)!}=\frac{k(k-1)}{n(n-1)}
\]

因此总答案为\(a \times \frac{k(k-1)}{n(n-1)}\),其中a为幸运点对的数量

所以只要求出幸运点对数量即可

对于每一个幸运数num[i],我们进行一次点分治,求出长度为num[i]的路径数(直接套点分治板子,先求长度>=num[i]的路径数,再减去长度>num[i]的路径数量),并累计进答案

注意最后n*(n-1)要用double,否则会爆int

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50005
using namespace std; int n,k;
struct edge{
int from;
int to;
int next;
}E[maxn<<1];
int ecnt=1;
int head[maxn];
inline void add_edge(int u,int v){
ecnt++;
E[ecnt].from=u;
E[ecnt].to=v;
E[ecnt].next=head[u];
head[u]=ecnt;
} int root=0,sum;
int f[maxn];
int sz[maxn];
int vis[maxn];
void get_root(int x,int fa){
sz[x]=1;
f[x]=0;
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa&&!vis[y]){
get_root(y,x);
sz[x]+=sz[y];
f[x]=max(f[x],sz[y]);
}
}
f[x]=max(f[x],sum-f[x]);
if(f[x]<f[root]) root=x;
} int cnt=0;
int deep[maxn];
int res[maxn];
void get_deep(int x,int fa){
res[++cnt]=deep[x];
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa&&!vis[y]){
deep[y]=deep[x]+1;
get_deep(y,x);
}
}
} int calc(int x,int d0){
deep[x]=d0;
cnt=0;
get_deep(x,0);
sort(res+1,res+1+cnt);
int l=1,r=cnt;
int ans1=0;
while(l<r){
if(res[l]+res[r]<=k){
ans1+=(r-l);
l++;
}else r--;
} l=1,r=cnt;
int ans2=0;
while(l<r){
if(res[l]+res[r]<k){
ans2+=(r-l);
l++;
}else r--;
}
return ans1-ans2;
} int ans=0;
void solve(int x){
vis[x]=1;
ans+=calc(x,0);
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(!vis[y]){
ans-=calc(y,1);
root=0;
sum=sz[y];
get_root(y,0);
solve(root);
}
}
} void divide_ini(){
memset(deep,0,sizeof(deep));
memset(f,0,sizeof(f));
memset(sz,0,sizeof(sz));
memset(vis,0,sizeof(vis));
root=0;
sum=n;
f[0]=n;
get_root(1,0);
} int m;
int num[maxn];
int main(){
int u,v;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d",&num[i]);
}
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=m;i++){
k=num[i];
divide_ini();
solve(root);
}
double k1,k2,k3;
if(n%3==0) k1=k2=k3=n/3;
else if(n%3==1){
k1=n/3+1;
k2=n/3;
k3=n/3;
}else{
k1=n/3+1;
k2=n/3+1;
k3=n/3;
}
printf("%.2lf\n",ans*k1*(k1-1)/((double)n*(n-1)));//强制转成double,防止溢出
printf("%.2lf\n",ans*k2*(k2-1)/((double)n*(n-1)));
printf("%.2lf\n",ans*k3*(k3-1)/((double)n*(n-1)));
}

BZOJ 4675(点分治)的更多相关文章

  1. bzoj 4025 二分图 分治+并查集/LCT

    bzoj 4025 二分图 [题目大意] 有n个点m条边,边会在start时刻出现在end时刻消失,求对于每一段时间,该图是不是一个二分图. 判断二分图的一个简单的方法:是否存在奇环 若存在奇环,就不 ...

  2. BZOJ 1468 & 点分治

    题意: 带权树,求距离小于k的点对数目. SOL: 参考http://blog.csdn.net/jiangshibiao/article/details/25738041解决了题意问题... 代码是 ...

  3. 【BZOJ 4059】 (分治暴力|扫描线+线段树)

    4059: [Cerc2012]Non-boring sequences Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 632  Solved: 22 ...

  4. bzoj 1176 CDQ分治

    思路:首先我们将问题转换一下,变成问在某个点左下角的权值和,那么每一个询问可以拆成4的这样的询问,然后 进行CDQ 分治,回溯的时候按x轴排序,然后用树状数组维护y的值. #include<bi ...

  5. bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...

  6. bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 首先考虑DP做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...

  7. bzoj 2599(点分治)

    2599: [IOI2011]Race Time Limit: 70 Sec  Memory Limit: 128 MBSubmit: 3642  Solved: 1081[Submit][Statu ...

  8. BZOJ 1537 cdq分治

    思路: 我只是想写一下cdq-- 二维偏序 一维排序 一维cdq分治 (我忘了归并排序怎么写了,,,) 写了个sort- 复杂度是O(nlog^2n) //By SiriusRen #include ...

  9. BZOJ 3262 cdq分治 OR 树套树

    注意判断 三个条件都一样的-- (CDQ分治 其实并不是很难理解 只是想不到--) CDQ分治: //By SiriusRen #include <cstdio> #include < ...

随机推荐

  1. pg_resetxlog - 重置一个 PostgreSQL 数据库集群的预写日志以及其它控制内容

    SYNOPSIS pg_resetxlog [ -f ] [ -n ] [ -o oid] [ -x xid] [ -l fileid,seg] datadir DESCRIPTION 描述 pg_r ...

  2. [POI2007]POW-The Flood(并查集)

    [POI2007]POW-The Flood Description AKD 市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD 市全被水淹没了.Blue Mary,AKD 市的市长,召集了 ...

  3. 2018-08-01-weekly

    Algorithm 4. Median of Two Sorted Arrays What 两个排序数组的中位数 How 两个数组合并到同一个数组,然后进行排序取中间值即可 Key Codes cla ...

  4. 【转载】Mysql注入点在limit关键字后面的利用方法

      描写sql注入利用方法的文章数不胜数,本文将描述一种比较特殊的场景. 细节 在一次测试中,我碰到了一个sql注入的问题,在网上没有搜到解决办法,当时的注入点是在limit关键字后面,数据库是MyS ...

  5. python tkinter实时显示曲线

    from tkinter import *from tkinter import ttkimport time#画窗口root = Tk()root.geometry('1000x500')root. ...

  6. navicat的使用(测试库和正式库同步)以及用plsql改表字段属性

    说明:数据库的操作,除了查询,最好先做好备份,比如数据同步.更新.修改或删除之类的: netstat -antp   查看mysql端口 firewall -cmd --list-all    查看防 ...

  7. Selenium-Switch与SelectApi介绍

    Switch 我们在UI自动化测试时,总会出现新建一个tab页面,弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...

  8. sql2000如何完美压缩.mdf文件

    --收缩数据库 dbcc shrinkdatabase('test_db') , ) --数据文件mdf , ) --日志文件ldf ) --更新

  9. ps磨皮的方法

    磨皮顾名思义就是将皮肤模糊掉,它可以去除皮肤上的一些斑点以及细纹,从而使皮肤看起来更加光滑.下面就是两张磨皮前后的对比图,很明显右边的人物的皮肤看起来要更好一些:给人的视觉效果也更年轻一点. 磨皮前后 ...

  10. 基于MyBatis实现Dao编程

    基于MyBatis实现Dao编程 1.建立mybatis-config.xml文件 <?xml version="1.0" encoding="UTF-8" ...