[AtCoder Educational DP Contest] V - Subtree(树形dp + 前缀积/后缀积)
problem
luogu
給一棵樹,對每一個節(jié)點染成黑色或白色。
對于每一個節(jié)點,求強制把這個節(jié)點染成黑色的情況下,所有的黑色節(jié)點組成一個聯(lián)通塊的染色方案數(shù),答案對 MMM 取模。
1≤n≤1e5,2≤M≤1e91\le n\le 1e5,2\le M\le 1e91≤n≤1e5,2≤M≤1e9。
solution
換根 dpdpdp。
設 f(i):f(i):f(i): 以 iii 為根的子樹,iii 為黑色的合法方案數(shù)。(全局是以 111 為根的)
則有:f(u)=∏v∈sonu(f(v)+1)f(u)=\prod_{v\in son_u}(f(v)+1)f(u)=∏v∈sonu??(f(v)+1)。加一是整棵子樹全為白色的方案數(shù)。
設 g(i):g(i):g(i): 以 iii 為根的子樹,iii 為黑色的合法方案數(shù)。(這里的子樹指代的是 iii 的祖先及兄弟,即去掉 iii 原來子樹的剩余部分)
顯然答案為 f(i)?g(i)f(i)*g(i)f(i)?g(i)。
考慮如何求出 g(i)g(i)g(i)。
對于一對父子關系 f(u)=∏(f(son)+1)f(u)=\prod(f(son)+1)f(u)=∏(f(son)+1),其中就有兒子提供的一個貢獻 f(v)+1f(v)+1f(v)+1,我們需要去掉。
即,g(v)=g(u)?∏(f(son)+1)f(v)+1g(v)=g(u)*\frac{\prod(f(son)+1)}{f(v)+1}g(v)=g(u)?f(v)+1∏(f(son)+1)?。
但是 MMM 并不是質數(shù),所以不能求逆元。
我們可以對每個 uuu 維護出兒子貢獻 ∏(f(v)+1)\prod(f(v)+1)∏(f(v)+1) 的前綴積和后綴積。
只要知道某個兒子在其兒子中的編號即可。
具體可見代碼實現(xiàn)。
code
#include <bits/stdc++.h> using namespace std; #define int long long #define maxn 100005 vector < int > pre[maxn], suf[maxn]; vector < int > G[maxn]; int f[maxn], g[maxn]; int n, mod; void dfs1( int u, int fa ) {f[u] = 1;for( int v : G[u] )if( v == fa ) continue;else dfs1( v, u ), f[u] = f[u] * (f[v] + 1) % mod;pre[u].resize( G[u].size() + 1, 1 );suf[u].resize( G[u].size() + 1, 1 );for( int i = 1;i < G[u].size();i ++ ) {pre[u][i] = pre[u][i - 1];if( G[u][i - 1] ^ fa ) pre[u][i] = pre[u][i] * (f[G[u][i - 1]] + 1) % mod;}for( int i = G[u].size() - 2;i >= 0;i -- ) {suf[u][i] = suf[u][i + 1];if( G[u][i + 1] ^ fa )suf[u][i] = suf[u][i] * (f[G[u][i + 1]] + 1) % mod;} } void dfs2( int u, int fa ) {for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa ) continue;g[v] = pre[u][i] * suf[u][i] % mod * g[u] % mod + 1;//加1是父親代表的子樹全為白 dfs2( v, u );} } signed main() {scanf( "%lld %lld", &n, &mod );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%lld %lld", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1( 1, 0 );g[1] = 1;dfs2( 1, 0 );for( int i = 1;i <= n;i ++ ) printf( "%lld\n", g[i] * f[i] % mod );return 0; }總結
以上是生活随笔為你收集整理的[AtCoder Educational DP Contest] V - Subtree(树形dp + 前缀积/后缀积)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FPGA-任务五、十字路口交通控制灯器系
- 下一篇: 文字转语音保存音频和在线朗读