正题

题目链接:https://ac.nowcoder.com/acm/contest/7745/E


题目大意

给出\(n\)个点的一棵树,每个点有一个选择权重\(a_i\)(有\(\frac{a_i}{\sum_{i=1}^na_i}\)的概率被选择)。

然后有一个序列\(w\)。随机选择两次点(可以相同)若它们之间距离为\(L\),那么困难值为\(w_L\)

求期望困难值。

\(1\leq n\leq 10^5,0\leq w_i\leq 10^8\)


解题思路

设\(p_i\)表示选择\(i\)的概率那么就是求

\[\sum_{i=1}^n\sum_{j=1}^np_ip_jw_{dis(i,j)}
\]

看起来很点分治就上点分治吧

怎么合并两个子树的距离,设\(u_i\)表示子树\(1\)中深度为\(i\)的概率和,\(v_i\)则表示子树\(2\)中的。

那么就有

\[ans=\sum_{i=1}\sum_{j=1}u_iv_iw_{i+j}=\sum_{i=1}w_{i}\sum_{j=1}u_jv_{i-j}
\]

看起来很卷积就上\(\text{NTT}\)吧

做起来比较麻烦,题解告诉我们可以直接计算整个树的然后再分别减去每个子树内的。

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

这下一雪我半年前考场调了半天长剖+NTT的前耻了


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e5+10,P=998244353;
struct node{
ll to,next;
}a[N<<1];
ll n,l,ans,root,num,mx,tot,ls[N],p[N],w[N];
ll r[N],g[N],siz[N],f[N],x[N];
bool v[N];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void addl(ll x,ll y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void NTT(ll *f,ll op){
for(ll i=0;i<l;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=l;p<<=1){
ll len=p>>1,tmp=power(3,(P-1)/p);
if(op==-1)tmp=power(tmp,P-2);
for(ll k=0;k<l;k+=p){
ll buf=1;
for(ll i=k;i<k+len;i++){
ll tt=buf*f[i+len]%P;
f[i+len]=(f[i]-tt+P)%P;
f[i]=(f[i]+tt)%P;
buf=buf*tmp%P;
}
}
}
if(op==-1){
ll invn=power(l,P-2);
for(ll i=0;i<l;i++)
f[i]=f[i]*invn%P;
}
return;
}
void GetL(ll n){
l=1;while(l<n)l<<=1;
for(ll i=0;i<l;i++)
r[i]=(r[i>>1]>>1)|((i&1)?(l>>1):0);
return;
}
void groot(ll x,ll fa){
siz[x]=1;g[x]=0;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa||v[y])continue;
groot(y,x);siz[x]+=siz[y];
g[x]=max(g[x],siz[y]);
}
g[x]=max(g[x],num-siz[x]);
if(g[x]<g[root])root=x;
return;
}
void calc(ll x,ll fa,ll dep){
(f[dep]+=p[x])%=P;
mx=max(mx,dep);
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa||v[y])continue;
calc(y,x,dep+1);
}
return;
}
void del(){
for(ll i=0;i<=mx;i++)f[i]=0;
mx=0;return;
}
void fuc(ll n,ll z){
GetL(2*n);
for(ll i=0;i<l;i++)x[i]=f[i];
NTT(x,1);
for(ll i=0;i<l;i++)x[i]=x[i]*x[i]%P;
NTT(x,-1);
for(ll i=0;i<l;i++)
(ans+=z*w[i]*x[i]%P)%=P;
return;
}
void solve(ll x){
v[x]=1;ll tal=num;
calc(x,x,0);fuc(mx+1,1);del();
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(v[y])continue;
calc(y,x,1);fuc(mx+1,-1);del();
}
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(v[y])continue;
num=(siz[y]>siz[x])?(tal-siz[x]):siz[y];
root=0;groot(y,x);solve(root);
}
return;
}
signed main()
{
scanf("%lld",&n);ll s=0;
for(ll i=1;i<=n;i++)
scanf("%lld",&p[i]),s+=p[i];
for(ll i=1;i<=n;i++)
p[i]=p[i]*power(s,P-2);
for(ll i=0;i<n;i++)scanf("%lld",&w[i]);
for(ll i=1;i<n;i++){
ll x,y;
scanf("%lld%lld",&x,&y);
addl(x,y);addl(y,x);
}
num=n;g[0]=1e9;
groot(1,1);
solve(1);
printf("%lld\n",(ans+P)%P);
return 0;
}

牛客练习赛71E-神奇的迷宫【点分治,NTT】的更多相关文章

  1. 牛客练习赛22C Bitset

    牛客练习赛22C 一共有 n个数,第 i 个数是 xi  xi 可以取 [li , ri] 中任意的一个值. 设 ,求 S 种类数. 感觉二进制真是一个神奇的东西. #include <iost ...

  2. 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D

    目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...

  3. 牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 逻辑,博弈 B

    牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 https://ac.nowcoder.com/acm/contest/218/B 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 2621 ...

  4. 牛客练习赛31 D 神器大师泰兹瑞与威穆 STL,模拟 A

    牛客练习赛31 D 神器大师泰兹瑞与威穆 https://ac.nowcoder.com/acm/contest/218/D 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 26214 ...

  5. 最小生成树--牛客练习赛43-C

    牛客练习赛43-C 链接: https://ac.nowcoder.com/acm/contest/548/C 来源:牛客网 题目描述 ​ 立华奏是一个刚刚开始学习 OI 的萌新. 最近,实力强大的 ...

  6. 牛客练习赛28-B(线段树,区间更新)

    牛客练习赛28 - B 传送门 题目 qn姐姐最好了~ ​ qn姐姐给你了一个长度为n的序列还有m次操作让你玩, ​ 1 l r 询问区间[l,r]内的元素和 ​ 2 l r 询问区间[l,r]内的 ...

  7. 牛客练习赛26:D-xor序列(线性基)

    链接:牛客练习赛26:D-xor序列(线性基) 题意:小a有n个数,他提出了一个很有意思的问题:他想知道对于任意的x, y,能否将x与这n个数中的任意多个数异或任意多次后变为y 题解:线性基 #inc ...

  8. [堆+贪心]牛客练习赛40-B

    传送门:牛客练习赛40 题面: 小A手头有 n 份任务,他可以以任意顺序完成这些任务,只有完成当前的任务后,他才能做下一个任务 第 i 个任务需要花费  x_i 的时间,同时完成第 i 个任务的时间不 ...

  9. 牛客练习赛 29 E 位运算?位运算!(线段树)

    题目链接  牛客练习赛29E 对$20$位分别建立线段树.首先$1$和$2$可以合起来搞(左移右移其实是等效的) 用个lazy标记下.转移的时候加个中间变量. $3$和$4$其实就是区间$01$覆盖操 ...

随机推荐

  1. git flow版本

    feature 分支:开发者进行功能开发的分支. develop 分支:对开发的功能进行集成的分支. release 分支:负责版本发布的分支. hotfix 分支:对线上缺陷进行修复工作的分支,热修 ...

  2. Mac 证书错误

    在 Mac 操作系统安装 Python 3.6 或以上版本时,可能会遇到证书错误:Error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify ...

  3. taro小程序展示富文本

    在微信小程序下会用到wxParse这个东西来达到html转换wxml的效果, taro小程序官方也给出了示例,地址 这里封装成自己的组件: import Taro, { Component } fro ...

  4. 栈编程和函数控制流: 从 continuation 与 CPS 讲到 call/cc 与协程

    原标题:尾递归优化 快速排序优化 CPS 变换 call/cc setjmp/longjmp coroutine 协程 栈编程和控制流 讲解 本文为部分函数式编程的扩展及最近接触编程语言控制流的学习和 ...

  5. C++11 shared_ptr智能指针(超级详细)

    在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如: 有些内存资源已经被释放,但指向它的指针并没 ...

  6. Qt MDI及其使用方法(详解版)

    统的应用程序设计中有多文档界面(Multi-document Interface,MDI)应用程序,Qt 为设计 MDI 应用程序提供了支持. 本节的实例 samp6_4 是一个 MDI 应用程序,程 ...

  7. Spring之属性注入

    时间:2017-1-31 23:38 --Bean的属性注入方式有三种注入方式:    1)接口注入:        定义一个接口,定义setName(String name)方法,定义一个类,实现该 ...

  8. Maven无法导入插件,pom文件报错

    最近在使用IDEA导入开源项目bootshiro,更新依赖的时候,发现有些插件无法导入,以致于pom文件一直报找不到该插件的错误 一开始就网上各种百度,无论怎么更换阿里云的镜像都导不进,最后想着试试自 ...

  9. 这些经常被忽视的SQL错误用法,你有没有踩过坑?

    之前已经讲过mysql的性能优化,感兴趣的朋友可以看看之前的文章,<史上最全的MySQL高性能优化实战总结!>.但是有些问题其实是我们自身的SQL语句有问题导致的.今天就来总结哪些经常被我 ...

  10. Learning to Compare: Relation Network for Few-Shot Learning 论文笔记

    主要原理: 和Siamese Neural Networks一样,将分类问题转换成两个输入的相似性问题. 和Siamese Neural Networks不同的是: Relation Network中 ...