题目链接:点击打开链接
题意:
给定n个点的树
问:
对于以i为根时,把树边黑白染色,使得任意点走到根的路径上不超过一条黑边,输出染色的方案数(mod 1e9+7)
思路:
显然i点的方案数 = i为根的子树的方案数 * 不包括i为根的子树的部分的方案数
首先以i为根的子树求一个方案数down[i]:for all son vj of i, down[i] = multiply down[j]
求不包括i子树的时候为了避免除法,对儿子的方案数求一个前缀积和后缀积即可
避免了使用逆元
#include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <vector> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> const double eps = 1e-8; const double pi = acos(-1.0); template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } using namespace std; typedef long long ll; const int N = 200100; const int mod = 1e9 + 7; int n; vector<int>G[N]; vector<ll>D[N], P[N]; ll down[N], up[N]; ll go[N]; void mul(ll &x, ll y){ x *= y; x %= mod; } void dfs_down(int u, int fa){ down[u] = 1; for (int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if (v == fa){ D[u].push_back(1); P[u].push_back(1); continue; } dfs_down(v, u); mul(down[u], down[v] + 1); D[u].push_back(down[v] + 1); P[u].push_back(down[v] + 1); } for (int i = 1; i < D[u].size(); i++) mul(D[u][i], D[u][i - 1]); for (int i = (int)P[u].size() - 2; i >= 0; i--) mul(P[u][i], P[u][i + 1]); } void dfs_up(int u, int fa, ll way){ up[u] = way; for (int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if (v == fa)continue; ll tmp = way; if (i && i < (int)D[u].size()) mul(tmp, D[u][i - 1]); if (i + 1 < P[u].size()) mul(tmp, P[u][i + 1]); dfs_up(v, u, tmp + 1); } } int main(){ rd(n); for (int i = 2, x; i <= n; i++){ rd(x); G[x].push_back(i); G[i].push_back(x); } dfs_down(1, 1); dfs_up(1, 1, 1); for (int i = 1; i <= n; i++)pt(down[i] * up[i] % mod), putchar(' '); return 0; }
时间: 2024-10-27 13:46:19