概率 樹規 熟練剖分

2022-03-27 09:32:40 字數 2018 閱讀 3007

根節點不一定是1,但是是乙個確定的點,看誰不是兒子就行了。。

這道題我們考慮從兒子推到根。設f[i][j]表示以i為根的子樹中,最長輕鏈長度為j的概率。

因為每乙個son被選為重兒子的概率相同,且重兒子對父親貢獻和輕兒子不同,所以要每乙個點為重兒子,之後挨個列舉每個兒子。這個效率是n^2,然後要列舉鏈的長度,如果列舉到size[root],相當於n^3,廢掉了。。但只要列舉到size[son]+1就好了。更大不會再有意義,概率一定為零。

在計算答案時要再次用到f陣列,所以要先存一下,再轉過去。

對於每一次枚舉重兒子時列舉所有兒子時的計算方法。g[i][j]表示i節點子樹中最長鏈長為0~j的概率之和。

f[i][j]=f[son][j]*g[i][j]+g[son][j]*f[i][j]-f[i][j]*f[son][j];(對於重兒子)

考慮一次向答案上新增乙個子節點。那麼父節點最長為j的鏈出現地方有兩種可能。1,出現在之前已經新增到答案中的子節點裡(f[i][j]),那麼這時新新增的子節點的長度只要在0~j中哪乙個都無所謂了。同理,最長j出現在新新增的節點中,那之前新增的多長也就無所謂了。。。

那麼對於輕兒子呢?不同於重兒子,輕兒子與父親的連邊會對答案造成貢獻,所以只要把son的j改成j-1即可。

最後統計答案:根節點子樹中最長輕鏈長為j的概率*j,加個和就好了。

對於除法,乘逆元即可。

注:最好別看我**,巨醜,還難理解。。。我把f和g陣列合二為一了。。。。

#pragma gcc optimize("o3")

#include

#include

#include

#include

#include

#define n 3005

#define mod 1000000007

#define ll long long

using namespace std;

int read()

while(x>='0'&&x<='9')

return

sum*f;

}struct roadlu[n*2];

int n,e,adj[n];

ll out[n],sz[n],g[n],h[n],f[n][n];

bool v[n];

inline ll cheng(ll x,int m)

return ans;

}inline void dfs(int x)

ll fm=cheng(out[x],mod-2);

for(int i=adj[x];i;i=lu[i].next)

}g[0]=h[0];h[0]=0;

for(int k=1;k<=sz[to]+1;k++)g[k]=(g[k-1]+h[k])%mod,h[k]=0;

}for(int j=sz[x];j>=1;j--)g[j]=(g[j]-g[j-1]+mod)%mod;

for(int j=0;j<=sz[x];j++)f[x][j]=(f[x][j]+g[j]*fm%mod)%mod;

}if(!adj[x])f[x][0]=1;

for(int i=1;i<=n;i++)f[x][i]=(f[x][i]+f[x][i-1])%mod;

}int main()

;adj[i]=e;}}

int root;

for(int i=1;i<=n;i++)if(!v[i])root=i;

dfs(root);

ll ans=0;

for(ll i=1;i<=n;i++)

ans=(ans+i*(f[root][i]-f[root][i-1]+mod)%mod)%mod;

cout<

}

bzoj 4147 Abs 熟練剖分

題目描述 給定一棵樹,設計資料結構支援以下操作 1 u v d 表示將路徑 u,v 加d 2 u v 表示詢問路徑 u,v 上點權絕對值的和 輸入 第一行兩個整數n和m,表示結點個數和運算元 接下來一行n個整數a i,表示點i的權值 接下來n 1行,每行兩個整數u,v表示存在一條 u,v 的邊 接下...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

樹鏈剖分 樹剖換根

這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...