正题

题目链接: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. shell脚本基本使用教程

    sh脚本的固定第一行 #!/bin/bash 变量 #!/bin/bash var1=1 var2=2 var3=$[var1+var2] echo "$var3" 传达参数 sh ...

  2. docker commit (从容器创建一个新的镜像)

    从容器创建一个新的镜像 docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] -a :提交的镜像作者: -c :使用Dockerfile指令来创建镜 ...

  3. C# 对SQlServer访问的完整类

    using System; using System.Collections.Generic; using System.Collections.Specialized; using System.C ...

  4. 回顾games101中的SSAA和MSAA

    回顾games101中的AA(抗锯齿) 前言 善于进行课后总结,可以更加巩固自己的知识和具体细节 锯齿(走样)产生的原因 本质上,在光栅化阶段中,用有限离散的数据想表示连续的(类似三角形的某一边),就 ...

  5. 真实机中安装CentOS

    前言 最近在b站上看了兄弟连老师的Linux教程,非常适合入门:https://www.bilibili.com/video/BV1mW411i7Qf 看完后就自己来试着玩下,正好手上有台空闲的电脑就 ...

  6. 解决 conda tensorflow failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED

    参考解决方案1:https://stackoverflow.com/questions/38303974/tensorflow-running-error-with-cublas 参考解决方案2:ht ...

  7. php实现验证码(数字、字母、汉字)

    验证码在表单实现越来越多了,但是用js的写的验证码,总觉得不方便,所以学习了下php实现的验证码.好吧,其实是没有事情干,但是又不想浪费时间,所以学习了下php实现验证码.正所谓,技多不压身.而且,也 ...

  8. adb shell 查看当前与用户交互的 activity

    adb shell dumpsys activity activities | grep mActivityComponent

  9. Disable_functions绕过整合

    转载 https://whoamianony.top/2021/03/13/Web安全/Bypass Disable_functions/ https://www.mi1k7ea.com/2019/0 ...

  10. Blazor 组件库开发指南

    翻译自 Waqas Anwar 2021年5月21日的文章 <A Developer's Guide To Blazor Component Libraries> [1] Blazor 的 ...