main
黄海 2 years ago
parent b0a73c4726
commit 6a8653ce10

@ -1,59 +1,61 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = N << 1;
#define int long long
#define endl "\n"
const int N = 100010;
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
int f[N], g[N], son[N], ans[N];
int n, mod;
vector<int> val[N], pre[N], suc[N];
vector<int> s[N];
int f[N], g[N];
void dfs1(int x, int fa) {
for (int v : s[x]) {
void dfs1(int u, int fa) {
int tmp = 1;
val[u].push_back(1);
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == fa) continue;
dfs1(v, x);
f[x] = f[x] * (f[v] + 1) % mod;
dfs1(v, u);
son[u]++;
val[u].push_back(f[v] + 1);
tmp = tmp * (f[v] + 1) % mod;
}
f[u] = tmp;
}
void dfs2(int x, int fa) {
int t = g[x];
for (int v : s[x]) {
if (v == fa) continue;
g[v] = g[v] * t % mod;
}
t = 1;
for (int v : s[x]) {
if (v == fa) continue;
g[v] = g[v] * t % mod, t = t * (f[v] + 1) % mod;
}
t = 1;
reverse(s[x].begin(), s[x].end());
for (int v : s[x]) {
if (v == fa) continue;
g[v] = g[v] * t % mod, t = t * (f[v] + 1) % mod;
}
for (int v : s[x]) {
void dfs2(int u, int fa) {
if (u == 1) g[u] = 1;
ans[u] = f[u] * g[u] % mod;
pre[u].resize(son[u] + 2);
suc[u].resize(son[u] + 2);
pre[u][0] = suc[u][son[u] + 1] = 1;
for (int i = 1; i <= son[u]; i++) pre[u][i] = (ll)pre[u][i - 1] * val[u][i] % mod;
for (int i = son[u]; i >= 1; i--) suc[u][i] = (ll)suc[u][i + 1] * val[u][i] % mod;
int m = 0;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == fa) continue;
g[v]++;
dfs2(v, x);
m++;
g[v] = g[u] * pre[u][m - 1] % mod * suc[u][m + 1] % mod;
g[v] = (g[v] + 1) % mod;
dfs2(v, u);
}
}
signed main() {
// 初始化链式前向星
memset(h, -1, sizeof h);
cin >> n >> mod;
for (int i = 1; i <= n; i++) f[i] = g[i] = 1;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
s[a].push_back(b), s[b].push_back(a);
add(a, b), add(b, a);
}
dfs1(1, 0);
dfs2(1, 0);
for (int i = 1; i <= n; ++i) cout << f[i] * g[i] % mod << endl;
for (int i = 1; i <= n; i++) cout << ans[i] << endl;
}

@ -0,0 +1 @@
<mxfile host="Electron" modified="2024-01-18T00:42:03.353Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.9.6 Chrome/89.0.4389.128 Electron/12.0.16 Safari/537.36" etag="OHYFicvGMxD0KwsFyfxJ" version="14.9.6" type="device"><diagram id="Zs30z2m-NJag_6JFkMF0" name="第 1 页">7Vptb9s2EP41BNoBKyRSL9RHSbZXrBuwIh+2fhrUWLGVylamyI6zX7878kRTluw4iBu7wZIgJo93vLvnXigqYSJdbH6ps7v579U0Lxl3phsmRoxzNwgFfCDlUVOiMNKEWV1MiWlLuCr+zYnoEHVVTPP7DmNTVWVT3HWJ19VymV83HVpW19VDl+2mKrta77JZ3iNcXWdln/pnMW3mRHWDaLvwMS9mc1IteagXFlnLTJ7cz7Np9WCRxJiJtK6qRo8WmzQvEbwWFy032bNqDKvzZXOMQOV+WzTR7d8fP99Ok39Wv34Wnz797HpkXPPYepxPAQCaLqslfCR1tVpOc9zHgVlVN/NqVi2z8requgOiC8TbvGkeKXzZqqmANG8WJa3mm6L5C8U/+DT7Yq2MNrSzmjy2k2VTP1pCOP1ir23F1KyVu6mWDRnCXZqnVVnVyj3hSPwGunYcvd0LKJHuq1V9nR9CkRIzq2d5c4CPm7BDveTVIge7Qa7Oy6wp1l07MkrcmeHbxhYGFN7nhNr/8UL9gftPRFvN/sjrAkDK68tPAXHWFND7rrNyRZpW/ZwoS+itmAoP86LJr+4y5fcDtPduoLP7O91wb4oNJsyTqDuTiaOiU5Tl/mis87rJN4fj0cePBHhEInTawO56/rDt3R6R5lbXbmknRzzq4XtZBXZ5vZQfWUjeWQvJ6cX1UnrpBYfMP2vI3IsN2RuszuCcoea9Y249EPyTnXP3TV19yy3gv0rf852BgLzCCej63RNQRGc+AV3+f929vO7EkXUXnrXFih8v1D/ODePYFJDnTAHRb70D9X+6K8aeRrqv8Z6gwXruhTVYrwf56wE+UV9P5v+LAA+cDt4+PzPe/hvH2/UvDPDgjQNuXlJcCuDhGwdchO5lAS7fOOCef2GAu0MpHpSgNvkKgxkObpifrJg/YmOfxWMWxWzssSRiMmpZQbXhNuK1oSB7wmJ/pUaSJbBDwGIHNxlPWJIymeLmME0C4ok8aylgMoaflWJKlbzPpFTcAYsmLBLW1hFqi1w2lmhiwhVPqJitHeMRi72hJeWkhA1DdFVqHtDrKRUjpcsotVUEyh/Y2UXbSMpBe2TI5ISNBZMOk3wAof2UfhAk2gc6wD6MRrhfuBMW8CtKWSwJesRHIQbIwk4EpocAoju27/v8MohJdCqeWPkBPFJRQgxk4lqoBogY4IA8KY4xlMCjxQFe5zjtPRgwN/QAeCC4/hZwrStOlYNgRkK+g7pO/jnKVGO8shPdkWgeBJGkvHYQ943HFywpPOoP2CeVNemAfcckBAKn8YJogbKwtY8r00dqYAGHSyM1ECwRlp+RipZoi1jSEgj2lGLSgUO69AkdXcsq9cE7zCeVNDIwZb52X1jna/d0hW5yirJ+7b5mYSsA+esDyL8jgPzMnZGkRqoQOO1MBWWQpJTeJjBPO7EApbHdpw4ExQTA6gt7YdtFq1uSO43vWViZgCiotWFkj32qaVN1Zx+1A8dqzUNtbtcdW1eERhJiE8Uj0IBOi48U5aD4rlJjoQUCtNEo6vTWXTDtnbW4llLHmxyjI8TjDp3xsGHQngdjjMJAcA+40++cRkXfVF+dGT75LpV27NvyoC5zYhk0tIVht4GkFMqYoyO4c4xs23CHeEAQvAczSu9Dhhl7WgyPPZh0YlP7YmLgKHmiuZ2qSnYTzWoAyZA7xir+6lbx/VYN2OljCumAmoyFKRQ1VZnSBwd95FMtRDrBnG0/pBNCtg9/iXokCpETm2eEEQeXuGMeNvFC4LzrgPj+p3cd89/3bmhwPWq6V7HuH4bo9bd9/SJSVhazJUzL/AZ3wKtWcZ2VMZEXxXRa7rv5dd+m7971TnB38wO/c3cbeN1pWOy7Wyi+2+Vt4Lr8vMQ0CW4eJQNMHewFqikk6hoEv5PkO4T5GpDHPyScKNBCDL3wxq+Wj4x3T5ANvVcn/WwQwcBNnj8/GWC6/edItWb9i6kY/wc=</diagram></mxfile>

@ -1275,50 +1275,39 @@ signed main() {
对于每一个节点 $i$,求强制把第 $i$ 节点染成黑色的情况下,所有的黑色节点组成一个联通块的染色方案数,答案对 $M$ 取模。
**分析**
树上求方案数,而且要求每一个顶点对应的方案数,还是在 $AT$ 的 $DP$ 列表里的,考虑进行换根$DP$。
题目要求我们求出对每一个点强制染黑的情形的答案,故考虑采用换根 $DP$。
先计算钦定 $1$ 号点为根并染黑的方案数。
**求解**
第一步,先求出以第 $i$ 个点为根的子树中,根节点是黑色的黑连通块数量,就是一个普通的树上 $DP$,状态从子节点转移,结果储存在
$dp[i]$ 里。
**状态转移方程**
设 $f_u$ 表示将 $u$ 号点染黑,且其子树内黑点构成连通块的方案数。易见,对于其每一个子节点
$v$,都有染黑和不染黑两种选择:染黑则方案数为 $f_v$ ;不染黑则 $v$ 的整棵子树都只能为白,方案数为 $1$。故
$$\large f_u= \prod_{v \in son_u} (f_v+1) $$
> **解释**
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202401180842993.png)
```cpp {.line-numbers}
void DP(int x,int fa){
for(int i:s[x]){
if(i!=fa){
DP(i,x);
dp[x]=dp[x]*(dp[i]+1)%m;//子树全白也是一种情况
}
}
}
```
第二步,求出第 $i$ 个节点通过它的父亲节点,与此节点的兄弟节点们及其子孙节点和此节点的祖先节点们,所能构成的黑连通块的总数,结果存在 $pd[i]$ 里。
这里有换根的思想。首先它的父亲肯定是黑的,这时把它的父亲节点视作根节点,把它自己及其子树删去,和第一步同样的方法求解。
**初始化**
当 $u$ 为叶子时,显然 $f_u =1$,与初始化要求相同。
```cpp {.line-numbers}
void PD(int x,int fa){
Int t=pd[x];
for(int i:s[x])//它的祖先们转移过来的
if(i!=fa)
pd[i]=pd[i]*t%m;
t=1;
for(int i:s[x])//它左侧的兄弟们转移过来的
if(i!=fa)
pd[i]=pd[i]*t%m,t=t*(dp[i]+1)%m;
t=1;
std::reverse(s[x].begin(),s[x].end());
for(int i:s[x])//它右侧的兄弟们转移过来的
if(i!=fa)
pd[i]=pd[i]*t%m,t=t*(dp[i]+1)%m;
for(int i:s[x])if(i!=fa){
++pd[i];
PD(i,x);
}
}
```
显而易见的,步骤一和步骤二中的答案互不相干,可以让节点上方随意排布,节点下方随意排布。根据乘法原理,答案即为
$dp[i] \times pd[i]$ 。
> 解释:**对于每一个点,求强制给该点染上黑色时,整棵树上的黑点构成一个连通块的染色方案数。** 这是题目的要求!当一个子树中只有一个点时,还要强制给该点染上黑色,那就只有一种方案。
现在考虑换根。不难理解,如果$v \in son[u]$,换根时消去 $v$ 对 $u$ 的贡献,再将 $u$ 的贡献乘到 $v$ 上。
- 消去 $v$ 对 $u$ 的贡献:
$\large f'_{u}=\frac{f_{u}}{f_v+1}$
- 将 $f'_u$ 的贡献乘到 $v$ 上:
$\large f'_v=f_v \times (f'_u+1)$
不过出现了一个小问题:**模数不保证是质数**,所以不能用直接乘逆元的方式来取模。
这里,对于每一个点 $u$,处理出 $f_{v∈son[u]}+1$ 的 **前缀积** 和 **后缀积**,即可解决求出消去一个子树贡献后的答案的问题。
#### [$AcWing$ $1148$ 秘密的牛奶运输](https://www.cnblogs.com/littlehb/p/16054005.html)
@ -1334,4 +1323,3 @@ https://www.cnblogs.com/DongPD/p/17498336.html

Loading…
Cancel
Save