BZOJ3451 Normal 期望、点分治、NTT
题目大意:给出一棵树,求对其进行随机点分治的复杂度期望
可以知道一个点的贡献就是其点分树上的深度,也就是这个点在点分树上的祖先数量+1。
根据期望的线性性,考虑一个点对\((x,y)\)在何时\(x\)能够是\(y\)的祖先,那么在\(x\)到\(y\)的路径上的所有点中\(x\)必须要是第一个被选中的点,否则要么点\(y\)变成点\(x\)的祖先,要么点\(x\)和点\(y\)会被分在不同的子树中。那么我们要求的就是\(\sum \frac{1}{dis_{x,y}}\),其中\(dis_{x,y}\)表示\(x\)到\(y\)路径上的点的数量。直接使用\(NTT\)统计路径长度即可。
注意在某一个分治中心进行合并时必须按照深度从小到大合并,否则复杂度是不正确的。
#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
while(!isdigit(c))
c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
}
const int MAXN = 1e5 + 10 , MOD = 998244353 , G = 3 , INV = 332748118;
struct Edge{
int end , upEd;
}Ed[MAXN << 1];
int head[MAXN] , ind[MAXN] , size[MAXN] , ans[MAXN];
int N , need , nSize , mSize , mInd , cntEd;
bool vis[MAXN];
long long inv_need;
vector < vector < int > > v;
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
inline int poww(long long a , int b){
int times = 1;
while(b){
if(b & 1)
times = times * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return times;
}
void NTT(vector < int > &v , int type){
for(int i = 0 ; i < need ; ++i)
if(i < ind[i])
swap(v[i] , v[ind[i]]);
for(int i = 1 ; i < need ; i <<= 1){
int wn = poww(type == 1 ? G : INV , (MOD - 1) / (i << 1));
for(int j = 0 ; j < need ; j += i << 1){
long long w = 1;
for(int k = 0 ; k < i ; ++k , w = w * wn % MOD){
int x = v[j + k] , y = v[i + j + k] * w % MOD;
v[j + k] = x + y >= MOD ? x + y - MOD : x + y;
v[i + j + k] = x < y ? x - y + MOD : x - y;
}
}
}
}
void getSize(int x){
vis[x] = 1;
++nSize;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
getSize(Ed[i].end);
vis[x] = 0;
}
void getRoot(int x){
vis[x] = 1;
int maxN = 0;
size[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
getRoot(Ed[i].end);
maxN = max(maxN , size[Ed[i].end]);
size[x] += size[Ed[i].end];
}
maxN = max(maxN , nSize - size[x]);
if(maxN < mSize){
mSize = maxN;
mInd = x;
}
vis[x] = 0;
}
void calc(vector < int > &v , int x , int l){
while(v.size() <= l)
v.push_back(0);
++v[l];
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
calc(v , Ed[i].end , l + 1);
vis[x] = 0;
}
bool cmp(vector < int > a , vector < int > b){
return a.size() < b.size();
}
void solve(int x){
nSize = 0;
mSize = INF;
getSize(x);
getRoot(x);
x = mInd;
vis[x] = 1;
v.clear();
vector < int > cur , ano;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
cur.clear();
calc(cur , Ed[i].end , 1);
v.push_back(cur);
}
cur.clear();
sort(v.begin() , v.end());
need = 1;
for(int i = 0 ; i < v.size() ; ++i){
while(need < cur.size() + v[i].size())
need <<= 1;
inv_need = poww(need , MOD - 2);
for(int j = 1 ; j < need ; ++j)
ind[j] = (ind[j >> 1] >> 1) | (j & 1 ? need >> 1 : 0);
while(cur.size() < need)
cur.push_back(0);
while(v[i].size() < need)
v[i].push_back(0);
ano.clear();
NTT(cur , 1);
NTT(v[i] , 1);
for(int j = 0 ; j < need ; ++j){
ano.push_back(1ll * cur[j] * v[i][j] % MOD);
cur[j] = cur[j] + v[i][j] >= MOD ? cur[j] + v[i][j] - MOD : cur[j] + v[i][j];
}
NTT(ano , -1);
NTT(cur , -1);
for(int j = 0 ; j < need ; ++j){
ans[j] += ano[j] * inv_need % MOD;
cur[j] = cur[j] * inv_need % MOD;
}
while(cur.back() == 0)
cur.pop_back();
}
for(int i = 1 ; i < need ; ++i)
ans[i] += cur[i];
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
solve(Ed[i].end);
}
int main(){
N = read();
for(int i = 1 ; i < N ; ++i){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
solve(1);
long double sum = 0;
for(int i = 1 ; i <= N ; ++i)
sum += ans[i] * 2.0 / (i + 1);
cout << fixed << setprecision(4) << sum + N;
return 0;
}
BZOJ3451 Normal 期望、点分治、NTT的更多相关文章
- BZOJ3451 Tyvj1953 Normal 【期望 + 点分治 + NTT】
题目链接 BZOJ3451 题解 考虑每个点产生的贡献,即为该点在点分树中的深度期望值 由于期望的线性,最后的答案就是每个点贡献之和 对于点对\((i,j)\),考虑\(j\)成为\(i\)祖先的概率 ...
- [BZOJ3451]normal 点分治,NTT
[BZOJ3451]normal 点分治,NTT 好久没更博了,咕咕咕. BZOJ3451权限题,上darkbzoj交吧. 一句话题意,求随机点分治的期望复杂度. 考虑计算每个点对的贡献:如果一个点在 ...
- [BZOJ3451]Normal(点分治+FFT)
[BZOJ3451]Normal(点分治+FFT) 题面 给你一棵 n个点的树,对这棵树进行随机点分治,每次随机一个点作为分治中心.定义消耗时间为每层分治的子树大小之和,求消耗时间的期望. 分析 根据 ...
- #565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)
题面 戳这里,题意简单易懂. 题解 首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(1\) ,每次进位会减少一个 \(1\) ,我们就可以考虑最后 \(1\) 的个数(也就是最后的和) ...
- 【BZOJ3451】Normal (点分治)
[BZOJ3451]Normal (点分治) 题面 BZOJ 题解 显然考虑每个点的贡献.但是发现似乎怎么算都不好计算其在点分树上的深度. 那么考虑一下这个点在点分树中每一次被计算的情况,显然就是其在 ...
- LOJ2541 PKUWC2018猎人杀(概率期望+容斥原理+生成函数+分治NTT)
考虑容斥,枚举一个子集S在1号猎人之后死.显然这个概率是w1/(Σwi+w1) (i∈S).于是我们统计出各种子集和的系数即可,造出一堆形如(-xwi+1)的生成函数,分治NTT卷起来就可以了. #i ...
- 【XSY3306】alpha - 线段树+分治NTT
题目来源:noi2019模拟测试赛(一) 题意: 题解: 这场三道神仙概率期望题……orzzzy 这题暴力$O(n^2)$有30分,但貌似比正解更难想……(其实正解挺好想的) 注意到一次操作实际上就是 ...
- [gdoi2018 day1]小学生图论题【分治NTT】
正题 题目大意 一张随机的\(n\)个点的竞赛图,给出它的\(m\)条相互无交简单路径,求这张竞赛图的期望强联通分量个数. \(1\leq n,m\leq 10^5\) 解题思路 先考虑\(m=0\) ...
- 【BZOJ-3456】城市规划 CDQ分治 + NTT
题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 Solution 这个问题可以考虑dp,利用补集思想 N个点的简单图总数量为$2^{ ...
随机推荐
- Linux 学习笔记之超详细基础linux命令 Part 1
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 说明:主要是在REHL Server 6操作系统下进行的测试 --字符界面虚拟终端与图形界面之间的切 方法:[ ...
- cve-list
dlink CVE-2018-17786 CVE-2018-17787 CVE-2018-17880 CVE-2018-17881 mongoose CVE-2018-10945 openwrt CV ...
- recovery 根据@/cache/recovery/block.map描述从data分区升级
随着android版本的更新,系统固件的大小也越来越大,升级包也越来越大,cache分区已经不够存储update.zip了,所以应用把update.zip下载到data分区,默认情况下data分区是可 ...
- Unity Chan 3D Asset
Unity Chan 3D Asset 我真的很久沒再家裡開unity,不過今天让我久违的開了 下载地址 :http://ref.gamer.com.tw/redir.php?url=http%3A ...
- DMZ 区域
下面对DMZ区域进行简要介绍:DMZ是网络的一个区域,介于外网与内网之间的一个特殊区域,也称隔离区.它不同于传统的防火墙设置,DMZ防火墙方案为要保护的内部网络增加了一道安全防线,通常认为是非常安全的 ...
- C#中的console类输入输出功能
Console.WriteLine() 直接将括号内内容显示在控制台界面中(相当于C语言printf()吧) Console.ReadLine()获取控制台用户自己输入的内容(功能和C语言scanf( ...
- kettle 合并记录步骤中的 关键字段和 比较字段的说明
该步骤用于将两个不同来源的数据合并,这两个来源的数据分别为旧数据和新数据,该步骤将旧数据和新数据按照指定的关键字匹配.比较.合并. 需要设置的参数: 旧数据来源:旧数据来源的步骤 新数据来源.新数据来 ...
- ccf--20131203--最大矩形
刚开始我是想依次计算i个相连矩形的面积,然后找出最大的面积,但是这种做法是时间复杂度是O(n*n),运行会超时. 这个是网上的一种做法,分别计算以第i个矩形作为高时,最大的面积.这就要以i为起始点,左 ...
- 浅copy与深copy举例
例1: #!/usr/bin/env python import copy d1 = {'x':1,'y':2,'z':[3,4.5]} d2 = d1 d3 = d1.copy() d4 = co ...
- 获取请求Url
/// <summary> /// 获取请求Url /// 例:http://www.text:1234 /// </summary> /// <returns>& ...